Docker教程-9-构建镜像并上传到DockerHub仓库
Posted 孔子-说
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Docker教程-9-构建镜像并上传到DockerHub仓库相关的知识,希望对你有一定的参考价值。
目录
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一致,并且尽量在末尾修改。
以上是关于Docker教程-9-构建镜像并上传到DockerHub仓库的主要内容,如果未能解决你的问题,请参考以下文章