侧边栏壁纸
博主头像
孔子说JAVA博主等级

成功只是一只沦落在鸡窝里的鹰,成功永远属于自信且有毅力的人!

  • 累计撰写 285 篇文章
  • 累计创建 125 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

Docker教程-9-构建镜像并上传到DockerHub仓库

孔子说JAVA
2021-10-21 / 0 评论 / 0 点赞 / 133 阅读 / 12,291 字 / 正在检测是否收录...

1、基于已有镜像构建镜像并上传到DockerHub

构建镜像有很多方法,用户可以从 Docker Hub 获取已有镜像并更新,也可以利用本地文件系统Dockerfile创建一个。

1.1 更改已安装的镜像容器

进入 mysql8.0.26 容器,命令:docker exec -it mysql8.0.26 bash,给容器安装上vim。

# 进入容器
docker exec -it mysql8.0.26 bash

# 测试vim命令结果:bash: vim: command not found
vim

# 更新索引
apt-get update

# 安装vim
apt-get install vim

# 测试vim命令结果:打开vim编辑器
vim

image-1649080084076

测试vim命令后退出容器

  • 使用 exit或按ctrl+p,ctrl+q 退出容器。

image-1649080107955

1.2 基于上述容器重新创建镜像

镜像的完整名称是 用户名称/仓库名称:TAG ,创建的镜像计划上传到dockerhub服务器,所以创建的镜像名为 kongzid/java:mysql8.0.26-vim 。查看镜像列表可以看到已经创建的镜像。

# mysql8.0.26为刚才修改的容器名称,也可以用容器id
docker commit mysql8.0.26 kongzid/java:mysql8.0.26-vim

# 查看镜像列表
docker images

image-1649080148746

1.3 上传镜像到DockerHub仓库

使用 docker login 登录DockerHub后,上传镜像。注意这里的镜像名称必须和hub中的仓库名称一致,否则将会抛出错误。

# 登录
docker login

# 上传镜像到DockerHub的java仓库
docker push kongzid/java:mysql8.0.26-vim

image-1649080183132

查看dockerhub仓库 kongzid/java 已经存在 tag为mysql8.0.26-vim的镜像 。可以用 docker pull kongzid/java:mysql8.0.26-vim 下载镜像到本地。

image-1649080219385

2、使用Dockerfile构建JDK+tomcat镜像

使用 docker commit 来扩展一个镜像比较简单,但是不方便在一个团队中分享。我们可以使用 docker build 来创建一个新的镜像。为此,首先需要创建一个 Dockerfile,包含一些如何创建镜像的指令。

2.1 准备好jdk和tomcat安装包等文件

Jdk 和 Tomcat 记得从官网下载,否则制作出来的镜像容易出现不兼容问题。准备修改好的 server.xml (修改连接和线程数),制作镜像时覆盖tomcat中的;准备好以下5个文件,放在同一目录下。

  • apache-tomcat-8.5.32.tar.gz :tomcat9安装包
  • jdk-8u181-linux-x64.tar.gz : jdk8安装包
  • readme.txt : 说明文件
  • Dockerfile : 大小写要规范(注意Dockerfile的D需要大写),官方命名 Dockerfile,build 会自动寻找这个文件,若不是这个名字build时需要 -f 指定
  • server.xml : tomcat的配置文件,修改了部分配置,若使用默认配置不需要准备

image-1649080308858

2.2 编写Dockerfile文件

vim Dockerfile ,文件内容如下:

# 指定操作的镜像
FROM ubuntu:20.04
 
# 维护者信息
MAINTAINER kongzi<153957433@qq.com>
 
# 覆盖相关文件
COPY readme.txt /usr/local/readme.txt
 
# 将 jdk 和 tomcat 添加到镜像ubuntu:20.04的/usr/local/目录下,ADD 命令会自动解压 将tar包解压到这个路径
ADD jdk-8u291-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.54.tar.gz /usr/local/
 
# 安装一下基本命令,一般非必要不建议安装,尽量减少镜像内容
# Dockerfile 中每一条指令都创建镜像的一层,把多个命令可以用 && 合并
# RUN buildDeps='net-tools vim' \
#     && apt-get update \
#     && apt-get install -y $buildDeps \
# 	&& apt-get purge -y --auto-remove $buildDeps
 
# 设置默认工作目录
ENV MYPATH /usr/local
WORKDIR $MYPATH
 
# 通过ENV来设置各种环境变量
ENV JAVA_HOME=/usr/local/jdk1.8.0_291
ENV JRE_HOME=/usr/local/jdk1.8.0_291/jre
ENV CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.54
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.54
ENV PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
ENV export JAVA_HOME JRE_HOME CLASSPATH PATH
# TZ在这里可以不设置,在容器启动的时候通过参数指定
ENV TZ="Asia/Shanghai"
# 可以设置tomcat参数
# ENV CATALINA_OPTS -Xms128m -Xmx1024m -XX:PermSize=64M -XX:MaxPermSize=512M
 
# 暴露端口8080
EXPOSE 8080
 
# 容器启动时运行tomcat && 拼接一些参数  tail -F 显示文件新追加的内容
CMD /usr/local/apache-tomcat-9.0.54/bin/catalina.sh run && tail -f /usr/local/apache-tomcat-9.0.54/logs/catalina.out

2.3 设置Dockerfile权限

设置Dockerfile权限: chmod 777 Dockerfile 。该命令表示将这个文件改成所有的用户都可读可写可执行,若当前操作用户为root或有操作权限的用户,则不需要执行该操作。

2.4 执行 docker build 构建镜像

根据配置完的dockerfile构建Docker镜像,在Dockerfile文件所在的目录下使用 docker build 命令,注意命令最后的点 .

docker build -t java/tomcat9jdk8:v1.0 .
  • -t  设置tag名称, 命名规则 registry/image:tag(若不添加版本号,默认latest)

image-1649080439344

镜像构建完成

image-1649080447747

$ docker build .  #默认使用当前目录下Dockerfile
$ docker  build . -f centosdockerfile  #其他名称dockerfile,需要指定
$ docker build -f /path/to/a/Dockerfile . #递归目录下的dockerfile
$ docker build -t ghostwritten/app . #指定镜像名
$ docker build -t ghostwritten/app:1.0.2 -t ghostwritten/app:latest . #指定多个tag
#Dockerfile文件中的每条指令会被独立执行,并会创建一个新镜像,Docker 会重用已生成的中间镜像,以加速docker build的构建速度,也可以通过--cache-from指定
$ docker build -t ghostwritten/app --cache-from 31f630c65071 . 
$ docker build -t ghostwritten/app --no-cache . #不使用缓存

2.5 查看刚刚构建的镜像

使用 docker images 命令查看刚刚构建的镜像,在镜像列表中已经可以看到。

image-1649080467560

2.6 测试镜像,运行容器

使用 docker run 命令运行容器,执行成功后使用 docker ps 命令可以查看到运行的容器进程。

docker run -it -p 8090:8080  \
--name tomcat9jdk8-my \
--privileged=true \
--restart=always \
-v /usr/local/docker/tomcat/tomcat9/webapps:/usr/local/tomcat/webapps \
-v /usr/local/docker/tomcat/tomcat9/conf:/usr/local/tomcat/conf \
-v /usr/local/docker/tomcat/tomcat9/logs:/usr/local/tomcat/logs \
-d java/tomcat9jdk8:v1.0
  • 默认情况下,tomcat会占用8080端口,所以在启动container的时候,指定了 -p 8090:8080,映射到宿主机端口就是8090。
  • -d 后台运行
  • –name tomcat9jdk8-my 容器名称
  • -v 挂载宿主机目录到tomcat下的webapps、conf、logs等,可以不指定
  • –privileged=true 设置拥有容器中的真正的root权限
  • java/tomcat9jdk8:v1.0 镜像的名称

image-1649080525421

附另外几种运行容器的命令:

# 只挂载代码(部署包)
docker run -it -p 8090:8080  \
--name tomcat9jdk8-my \
--privileged=true \
--restart=always \
-v /usr/local/docker/tomcat/tomcat9/webapps:/usr/local/tomcat/webapps \
-d java/tomcat9jdk8:v1.0

# 只挂载挂载日志
docker run -it -p 8090:8080  \
--name tomcat9jdk8-my \
--privileged=true \
--restart=always \
-v /usr/local/docker/tomcat/tomcat9/logs:/usr/local/tomcat/logs \
-d java/tomcat9jdk8:v1.0

# 只挂载配置文件catalina.sh(调整内存)
docker run -it -p 8090:8080  \
--name tomcat9jdk8-my \
--privileged=true \
--restart=always \
-v /usr/local/docker/tomcat/tomcat9/bin/catalina.sh:/usr/local/tomcat/bin/catalina.sh \
-d java/tomcat9jdk8:v1.0

# 只挂载配置文件server.xml(调整端口和线程数)
docker run -it -p 8090:8080  \
--name tomcat9jdk8-my \
--privileged=true \
--restart=always \
-v /usr/local/docker/tomcat/tomcat9/conf/server.xml:/usr/local/tomcat/conf/server.xml \
-d java/tomcat9jdk8:v1.0

2.7 访问测试

可以使用 curl http://localhost:8090 命令测试tomcat服务是否正常,也可以通过浏览器访问该网址。

image-1649080561383

2.8 tomcat发布项目

若使用 挂载目录的方式 运行的容器,只需要把项目war包放于挂载的webapps目录下,重启容器即可。

若使用 非挂载的方式 运行的容器,需要把war包放入容器内部的webapps目录下,重启容器即可。

  • 宿主机中使用命令如:docker cp /usr/demo.war tomcat9jdk8-my:/usr/local/tomcat/webapps
  • 进入容器内部命令: docker exec -it tomcat9jdk8-my /bin/bash

2.9 上传镜像到DockerHub仓库

1)使用docker hub 规范修改镜像的标签

# 使用docker hub 规范修改镜像的标签,注意命令的前后不能有空格
# docker tag <existing-image>  <hub-user>/<repo-name>[:<tag>]  
docker tag java/tomcat9jdk8:v1.0 kongzid/java:tomcat9jdk8V1

image-1649080688161

2)命令行登录docker hub并上传镜像

# 登录
docker login

# 上传镜像到DockerHub的java仓库
docker push kongzid/java:tomcat9jdk8V1

image-1649080705863

3)网页登录docker hub查看镜像

登录 Docker Hub 仓库中查看,可以看到已上传的镜像。

image-1649080741654

2.10 附环境变量JAVA_OPTS的设置

环境变量【JAVA_OPTS】可以在容器启动时指定:-e JAVA_OPTS='-server -Dfile.encoding=UTF-8 -Xms2g -Xmx2g -Xmn512m -Xss512K ..............',也可以在 Dockerfile文件 中指定。

ENV JAVA_OPTS="\
-server \
-Xms3g \
-Xmx3g \
-Xmn512m \
-Xss512K \
-Dfile.encoding=UTF-8 \
-verbose:gc \
-XX:+UseConcMarkSweepGC \
-XX:MaxTenuringThreshold=10 \
-XX:+ExplicitGCInvokesConcurrent \
-XX:GCTimeRatio=19 \
-XX:+UseParNewGC \
-XX:+UseCMSCompactAtFullCollection \
-XX:CMSFullGCsBeforeCompaction=10 \
-XX:+CMSClassUnloadingEnabled \
-XX:+CMSParallelRemarkEnabled \
-XX:CMSInitiatingOccupancyFraction=50 \
-Xnoclassgc \
-XX:SoftRefLRUPolicyMSPerMB=0"

3、Dockerfile参考示例

3.1 示例1:构建Wordpress + nginx运行环境

# 指定基于的基础镜像
FROM ubuntu:14.04

# 维护者信息
MAINTAINER Eugene Ware <eugene@noblesamurai.com>

# Keep upstart from complaining
RUN dpkg-divert --local --rename --add /sbin/initctl
RUN ln -sf /bin/true /sbin/initctl

# Let the conatiner know that there is no tty
ENV DEBIAN_FRONTEND noninteractive

RUN apt-get update
RUN apt-get -y upgrade

# Basic Requirements
RUN apt-get -y install mysql-server mysql-client nginx php5-fpm php5-mysql php-apc pwgen python-setuptools curl git unzip

# Wordpress Requirements
RUN apt-get -y install php5-curl php5-gd php5-intl php-pear php5-imagick php5-imap php5-mcrypt php5-memcache php5-ming php5-ps php5-pspell php5-recode php5-sqlite php5-tidy php5-xmlrpc php5-xsl

# mysql config, 配置MySQL运行参数
RUN sed -i -e"s/^bind-address\s*=\s*127.0.0.1/bind-address = 0.0.0.0/" /etc/mysql/my.cnf

# nginx config, 配置Nginx运行参数
RUN sed -i -e"s/keepalive_timeout\s*65/keepalive_timeout 2/" /etc/nginx/nginx.conf
RUN sed -i -e"s/keepalive_timeout 2/keepalive_timeout 2;\n\tclient_max_body_size 100m/" /etc/nginx/nginx.conf
RUN echo "daemon off;" >> /etc/nginx/nginx.conf

# php-fpm config
RUN sed -i -e "s/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/g" /etc/php5/fpm/php.ini
RUN sed -i -e "s/upload_max_filesize\s*=\s*2M/upload_max_filesize = 100M/g" /etc/php5/fpm/php.ini
RUN sed -i -e "s/post_max_size\s*=\s*8M/post_max_size = 100M/g" /etc/php5/fpm/php.ini
RUN sed -i -e "s/;daemonize\s*=\s*yes/daemonize = no/g" /etc/php5/fpm/php-fpm.conf
RUN sed -i -e "s/;catch_workers_output\s*=\s*yes/catch_workers_output = yes/g" /etc/php5/fpm/pool.d/www.conf
RUN find /etc/php5/cli/conf.d/ -name "*.ini" -exec sed -i -re 's/^(\s*)#(.*)/\1;\2/g' {} \;

# nginx site conf,将本地Nginx配置文件复制到容器中的目录
ADD ./nginx-site.conf /etc/nginx/sites-available/default

# Supervisor Config
RUN /usr/bin/easy_install supervisor
RUN /usr/bin/easy_install supervisor-stdout
ADD ./supervisord.conf /etc/supervisord.conf

# Install Wordpress
ADD https://wordpress.org/latest.tar.gz /usr/share/nginx/latest.tar.gz
RUN cd /usr/share/nginx/ && tar xvf latest.tar.gz && rm latest.tar.gz
RUN mv /usr/share/nginx/html/5* /usr/share/nginx/wordpress
RUN rm -rf /usr/share/nginx/www
RUN mv /usr/share/nginx/wordpress /usr/share/nginx/www
RUN chown -R www-data:www-data /usr/share/nginx/www

# Wordpress Initialization and Startup Script
ADD ./start.sh /start.sh
RUN chmod 755 /start.sh

# private expose
EXPOSE 3306
EXPOSE 80

# volume for mysql database and wordpress install
VOLUME ["/var/lib/mysql", "/usr/share/nginx/www"]

# 容器启动时执行命令
CMD ["/bin/bash", "/start.sh"]

3.2 示例2:构建Ruby on Rails环境

# 指定基础镜像
FROM fcat/ubuntu-universe:12.04

# development tools
RUN apt-get -qy install git vim tmux

# ruby 1.9.3 and build dependencies
RUN apt-get -qy install ruby1.9.1 ruby1.9.1-dev build-essential libpq-dev libv8-dev libsqlite3-dev

# bundler
RUN gem install bundler

# create a "rails" user
# the Rails application will live in the /rails directory
RUN adduser --disabled-password --home=/rails --gecos "" rails

# copy the Rails app
# we assume we have cloned the "docrails" repository locally
#  and it is clean; see the "prepare" script
ADD docrails/guides/code/getting_started /rails

# Make sure we have rights on the rails folder
RUN chown rails -R /rails

# copy and execute the setup script
# this will run bundler, setup the database, etc.
ADD scripts/setup /setup
RUN su rails -c /setup

# copy the start script
ADD scripts/start /start

EXPOSE 3000

# 创建用户
USER rails

# 设置容器启动命令
CMD /start

3.3 示例3: 构建Nginx运行环境

# 指定基础镜像
FROM sameersbn/ubuntu:14.04.20161014

# 维护者信息
MAINTAINER sameer@damagehead.com

# 设置环境
ENV RTMP_VERSION=1.1.10 \
    NPS_VERSION=1.11.33.4 \
    LIBAV_VERSION=11.8 \
    NGINX_VERSION=1.10.1 \
    NGINX_USER=www-data \
    NGINX_SITECONF_DIR=/etc/nginx/sites-enabled \
    NGINX_LOG_DIR=/var/log/nginx \
    NGINX_TEMP_DIR=/var/lib/nginx \
    NGINX_SETUP_DIR=/var/cache/nginx

# 设置构建时变量,镜像建立完成后就失效
ARG BUILD_LIBAV=false
ARG WITH_DEBUG=false
ARG WITH_PAGESPEED=true
ARG WITH_RTMP=true

# 复制本地文件到容器目录中
COPY setup/ ${NGINX_SETUP_DIR}/
RUN bash ${NGINX_SETUP_DIR}/install.sh

# 复制本地配置文件到容器目录中
COPY nginx.conf /etc/nginx/nginx.conf
COPY entrypoint.sh /sbin/entrypoint.sh

# 运行指令
RUN chmod 755 /sbin/entrypoint.sh

# 允许指定的端口
EXPOSE 80/tcp 443/tcp 1935/tcp

# 指定网站目录挂载点
VOLUME ["${NGINX_SITECONF_DIR}"]

ENTRYPOINT ["/sbin/entrypoint.sh"]
CMD ["/usr/sbin/nginx"]

3.4 示例4:构建Postgres镜像

# 指定基础镜像
FROM sameersbn/ubuntu:14.04.20161014

# 维护者信息
MAINTAINER sameer@damagehead.com

# 设置环境变量
ENV PG_APP_HOME="/etc/docker-postgresql"\
    PG_VERSION=9.5 \
    PG_USER=postgres \
    PG_HOME=/var/lib/postgresql \
    PG_RUNDIR=/run/postgresql \
    PG_LOGDIR=/var/log/postgresql \
    PG_CERTDIR=/etc/postgresql/certs

ENV PG_BINDIR=/usr/lib/postgresql/${PG_VERSION}/bin \
    PG_DATADIR=${PG_HOME}/${PG_VERSION}/main

# 下载PostgreSQL
RUN wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \
 && echo 'deb http://apt.postgresql.org/pub/repos/apt/ trusty-pgdg main' > /etc/apt/sources.list.d/pgdg.list \
 && apt-get update \
 && DEBIAN_FRONTEND=noninteractive apt-get install -y acl \
      postgresql-${PG_VERSION} postgresql-client-${PG_VERSION} postgresql-contrib-${PG_VERSION} \
 && ln -sf ${PG_DATADIR}/postgresql.conf /etc/postgresql/${PG_VERSION}/main/postgresql.conf \
 && ln -sf ${PG_DATADIR}/pg_hba.conf /etc/postgresql/${PG_VERSION}/main/pg_hba.conf \
 && ln -sf ${PG_DATADIR}/pg_ident.conf /etc/postgresql/${PG_VERSION}/main/pg_ident.conf \
 && rm -rf ${PG_HOME} \
 && rm -rf /var/lib/apt/lists/*

COPY runtime/ ${PG_APP_HOME}/
COPY entrypoint.sh /sbin/entrypoint.sh
RUN chmod 755 /sbin/entrypoint.sh

# 指定端口
EXPOSE 5432/tcp

# 指定数据挂载点
VOLUME ["${PG_HOME}", "${PG_RUNDIR}"]

# 切换目录
WORKDIR ${PG_HOME}

# 设置容器启动时执行命令
ENTRYPOINT ["/sbin/entrypoint.sh"]

4、Dockerfile最佳实践

4.1 使用.dockerignore文件

为了在docker build过程中更快上传和更加高效,应该使用一个.dockerignore文件用来排除构建镜像时不需要的文件或目录。例如,除非.git在构建过程中需要用到,否则你应该将它添加到.dockerignore文件中,这样可以节省很多时间。

4.2 避免安装不必要的软件包

为了降低复杂性、依赖性、文件大小以及构建时间,应该避免安装额外的或不必要的包。例如,不需要在一个数据库镜像中安装一个文本编辑器。

4.3 每个容器都跑一个进程

在大多数情况下,一个容器应该只单独跑一个程序。解耦应用到多个容器使其更容易横向扩展和重用。如果一个服务依赖另外一个服务,可以参考 Linking Containers Together。

4.4 最小化层

我们知道每执行一个指令,都会有一次镜像的提交,镜像是分层的结构,对于 Dockerfile,应该找到可读性和最小化层之间的平衡。

4.5 多行参数排序

如果可能,通过字母顺序来排序,这样可以避免安装包的重复并且更容易更新列表,另外可读性也会更强,添加一个空行使用 \ 换行:

RUN apt-get update && apt-get install -y \
  bzr \
  cvs \
  git \
  mercurial \
  subversion

4.6 创建缓存

镜像构建过程中会按照 Dockerfile 的顺序依次执行,每执行一次指令 Docker 会寻找是否有存在的镜像缓存可复用,如果没有则创建新的镜像。如果不想使用缓存,则可以在 docker build 时添加 --no-cache=true 选项。

  • 从基础镜像开始就已经在缓存中了,下一个指令会对比所有的子镜像寻找是否执行相同的指令,如果没有则缓存失效。在大多数情况下只对比 Dockerfile 指令和子镜像就足够了。ADD 和 COPY 指令除外,执行 ADD 和 COPY 时存放到镜像的文件也是需要检查的,完成一个文件的校验之后再利用这个校验在缓存中查找,如果检测的文件改变则缓存失效。RUN apt-get -y update 命令只检查命令是否匹配,如果匹配就不会再执行更新了。

  • 为了有效地利用缓存,你需要保持你的Dockerfile一致,并且尽量在末尾修改。

0

评论区