转自Docker教程-9-构建镜像并上传到DockerHub仓库,更优体验http://www.kongzid.com/
目录
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
测试vim命令后退出容器
使用exit或按ctrl+p,ctrl+q退出容器。
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
1.3 上传镜像到DockerHub仓库
使用docker login登录DockerHub后,上传镜像。注意这里的镜像名称必须和hub中的仓库名称一致,否则将会抛出错误。
# 登录 docker login # 上传镜像到DockerHub的java仓库 docker push kongzid/java:mysql8.0.26-vim
查看dockerhub仓库 kongzid/java 已经存在tag为mysql8.0.26-vim的镜像。可以用docker pull kongzid/java:mysql8.0.26-vim下载镜像到本地。
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的配置文件,修改了部分配置,若使用默认配置不需要准备
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)
镜像构建完成
2.5 查看刚刚构建的镜像
使用 docker images 命令查看刚刚构建的镜像,在镜像列表中已经可以看到。
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 镜像的名称
附另外几种运行容器的命令:
# 只挂载代码(部署包) 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服务是否正常,也可以通过浏览器访问该网址。
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
2)命令行登录docker hub并上传镜像
# 登录 docker login # 上传镜像到DockerHub的java仓库 docker push kongzid/java:tomcat9jdk8V1
3)网页登录docker hub查看镜像
登录 Docker Hub 仓库中查看,可以看到已上传的镜像。
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参考示例
示例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"]
示例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: 构建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"]
示例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一致,并且尽量在末尾修改。
原文链接:https://blog.csdn.net/carefree31441/article/details/120884660?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168623078216800211542160%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=168623078216800211542160&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~times_rank-16-120884660-null-null.268%5Ev1%5Ekoosearch&utm_term=docker%E3%80%81wordpress%E3%80%81wordpress%E5%BB%BA%E7%AB%99%E3%80%81wordpress%E4%B8%BB%E9%A2%98%E3%80%81%E5%AE%B9%E5%99%A8%E9%95%9C%E5%83%8F%E3%80%81