• docker入门 更新镜像 构建镜像


    A 构建镜像

    1 创建方式

    • 更新镜像:使用docker commit命令

    • 构建镜像:使用docker build命令,需要创建Dockerfile文件

    2 Dockerfile

    Dockerfile是用来构建Docker镜像的文件,是由一系列指令和参数构成的脚本,从FROM命令开始,紧接着各种命令、参数等,最终会生成一个新的镜像。

    第一条指令必须是FROM,指定Base Image基础镜像,指令按从上往下的顺序,依次执行,每条指令都会创建一个新的镜像层并提交

    FROM:指定基础镜像,即当前新镜像是基于哪个镜像的
    MAINTAINER:指定作者
    RUN:指定镜像构建过程中要运行的命令
    ENV:设置环境变量
    WORKDIR:指定默认的工作目录,即进入容器后默认进入的目录
    VOLUME:创建挂载点,也称容器数据卷,用于数据共享和持久化
    CMD:指定容器启动时要运行的命令,与RUN不同的是, 这些命令不是在镜像构建过程中执行的
    ENTRYPOINT:指定容器启动时要运行的命令
    COPY:拷贝文件/目录到镜像中
    ADD:拷贝文件到镜像中,且会自动解压缩
    EXPOSE:指定对外暴露的端口
    

    分析Dockerfile

    分析Dockerfile(tomcat:8.5.16-jre8)如下

    原文地址:https://www.cnblogs.com/dfengwei/p/7144937.html

    Dockerfile地址:https://github.com/docker-library/tomcat/blob/master/8.5/jre8/Dockerfile

    注意,这里以master分支的Dockerfile链接为例,和DockerHub上的Dockerfile链接可能会不一致

    #本镜像的基础镜像。有兴趣的话,可以自行在DockerHub上搜索openjdk,分析官方的openjdk镜像的Dockerfile文件。这里为什么不用oracle提供的jdk(jre)?简单地讲,版权问题。
    FROM openjdk:8-jre
    
    #声明CATALINA_HOME环境变量,这个变量大家都了解。
    ENV CATALINA_HOME /usr/local/tomcat
    #将Tomcat下的bin路径加入到PATH环境变量中。
    ENV PATH $CATALINA_HOME/bin:$PATH
    #创建tomcat路径。
    RUN mkdir -p "$CATALINA_HOME"
    #指定RUN、CMD、ENTRYPOINT命令的当前工作路径。
    WORKDIR $CATALINA_HOME
    
    #Tomcat Native路径配置。
    ENV TOMCAT_NATIVE_LIBDIR $CATALINA_HOME/native-jni-lib
    #将TOMCAT_NATIVE_LIBDIR加入到LD_LIBRARY_PATH环境变量中,这样Tomcat在查找Tomcat Native相关的动态链接库时,会去查找TOMCAT_NATIVE_LIBDIR环境变量指定的路径。
    ENV LD_LIBRARY_PATH ${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$TOMCAT_NATIVE_LIBDIR
    
    #检查、更新OpenSSL,这块的细节我没深究。
    ENV OPENSSL_VERSION 1.1.0f-3
    RUN { \
    		echo 'deb http://deb.debian.org/debian stretch main'; \
    	} > /etc/apt/sources.list.d/stretch.list \
    	&& { \
    		echo 'Package: *'; \
    		echo 'Pin: release n=stretch'; \
    		echo 'Pin-Priority: -10'; \
    		echo; \
    		echo 'Package: openssl libssl*'; \
    		echo "Pin: version $OPENSSL_VERSION"; \
    		echo 'Pin-Priority: 990'; \
    	} > /etc/apt/preferences.d/stretch-openssl
    RUN apt-get update && apt-get install -y --no-install-recommends \
    		libapr1 \
    		openssl="$OPENSSL_VERSION" \
    	&& rm -rf /var/lib/apt/lists/*
    
    #从key服务器导入key,用于验证tomcat压缩文件的签名,这块也没深究。
    ENV GPG_KEYS 05AB33110949707C93A279E3D3EFE6B686867BA6 07E48665A34DCAFAE522E5E6266191C37C037D42 47309207D818FFD8DCD3F83F1931D684307A10A5 541FBE7D8F78B25E055DDEE13C370389288584E7 61B832AC2F1C5A90F0F9B00A1C506407564C17A3 713DA88BE50911535FE716F5208B0AB1D63011C7 79F7026C690BAA50B92CD8B66A3AD3F4F22C4FED 9BA44C2621385CB966EBA586F72C284D731FABEE A27677289986DB50844682F8ACB77FC2E86E29AC A9C5DF4D22E99998D9875A5110C01C5A2F6059E7 DCFD35E0BF8CA7344752DE8B6FB21E8933C60243 F3A04C595DB5B6A5F1ECA43E3B7BBB100D811BBE F7DA48BB64BCB84ECBA7EE6935CD23C10D498E23
    RUN set -ex; \
    	for key in $GPG_KEYS; do \
    		gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; \
    	done
    
    #Tomcat相关文件的版本。
    ENV TOMCAT_MAJOR 8
    ENV TOMCAT_VERSION 8.5.16
    
    #Tomcat相关文件下载地址。
    ENV TOMCAT_TGZ_URL https://www.apache.org/dyn/closer.cgi?action=download&filename=tomcat/tomcat-$TOMCAT_MAJOR/v$TOMCAT_VERSION/bin/apache-tomcat-$TOMCAT_VERSION.tar.gz
    ENV TOMCAT_ASC_URL https://www.apache.org/dist/tomcat/tomcat-$TOMCAT_MAJOR/v$TOMCAT_VERSION/bin/apache-tomcat-$TOMCAT_VERSION.tar.gz.asc
    
    #执行命令
    RUN set -x \
    	\
    	#下载Tomcat压缩文件
    	&& wget -O tomcat.tar.gz "$TOMCAT_TGZ_URL" \
    	&& wget -O tomcat.tar.gz.asc "$TOMCAT_ASC_URL" \
    	#进行签名验证
    	&& gpg --batch --verify tomcat.tar.gz.asc tomcat.tar.gz \
    	#解压Tomcat
    	&& tar -xvf tomcat.tar.gz --strip-components=1 \
    	# 删除供Windows系统使用的.bat文件
    	&& rm bin/*.bat \
    	# 删除压缩文件
    	&& rm tomcat.tar.gz* \
    	\
    	#安装Tomcat Native
    	&& nativeBuildDir="$(mktemp -d)" \
    	&& tar -xvf bin/tomcat-native.tar.gz -C "$nativeBuildDir" --strip-components=1 \
    	&& nativeBuildDeps=" \
    		dpkg-dev \
    		gcc \
    		libapr1-dev \
    		libssl-dev \
    		make \
    		openjdk-${JAVA_VERSION%%[-~bu]*}-jdk=$JAVA_DEBIAN_VERSION \
    	" \
    	&& apt-get update && apt-get install -y --no-install-recommends $nativeBuildDeps && rm -rf /var/lib/apt/lists/* \
    	&& ( \
    		export CATALINA_HOME="$PWD" \
    		&& cd "$nativeBuildDir/native" \
    		&& gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)" \
    		&& ./configure \
    			--build="$gnuArch" \
    			--libdir="$TOMCAT_NATIVE_LIBDIR" \
    			--prefix="$CATALINA_HOME" \
    			--with-apr="$(which apr-1-config)" \
    			--with-java-home="$(docker-java-home)" \
    			--with-ssl=yes \
    		&& make -j "$(nproc)" \
    		&& make install \
    	) \
    	&& apt-get purge -y --auto-remove $nativeBuildDeps \
    	&& rm -rf "$nativeBuildDir" \
    	&& rm bin/tomcat-native.tar.gz
    
    #验证Tomcat Native是否安装成功
    RUN set -e \
    	&& nativeLines="$(catalina.sh configtest 2>&1)" \
    	&& nativeLines="$(echo "$nativeLines" | grep 'Apache Tomcat Native')" \
    	&& nativeLines="$(echo "$nativeLines" | sort -u)" \
    	&& if ! echo "$nativeLines" | grep 'INFO: Loaded APR based Apache Tomcat Native library' >&2; then \
    		echo >&2 "$nativeLines"; \
    		exit 1; \
    	fi
    
    #暴露8080端口
    EXPOSE 8080
    #容器启动时执行的命令。
    CMD ["catalina.sh", "run"]
    

    此Dockerfile的主要功能可归纳为:

    1. 以openjdk镜像为基础镜像进行构建。
    2. 安装Tomcat Native,及其依赖库(比如APR、OpenSSL等)。验证是否正确安装。
    3. 下载Tomcat,检查签名,解压、清除无用文件等。
    4. 暴露8080端口,配置入口命令。

    3 自定义tomcat镜像

    原文地址:https://www.cnblogs.com/uncleyong/p/8894133.html

    3.1 创建Dockerfile文件

    [root@localhost mydocker]# pwd
    /data/mydocker
    [root@localhost mydocker]# ll
    total 193708
    -rw-r--r-- 1 root root  10835556 Apr 12  2019 apache-tomcat-9.0.19.tar.gz
    -rwxr--r-- 1 root root       446 Dec 20 16:44 Dockerfile
    -rwxr--r-- 1 root root 187513052 Dec 20 16:35 openjdk-11.0.2_linux-x64_bin.tar.gz
    

    Dockerfile文件内容

    FROM centos
    MAINTAINER testname
     
    # 拷贝文件
    ADD openjdk-11.0.2_linux-x64_bin.tar.gz /usr/local
    ADD apache-tomcat-9.0.19.tar.gz /usr/local
     
    # 配置环境变量
    ENV JAVA_HOME /usr/local/jdk-11.0.2
    ENV CLASSPATH .:$JAVA_HOME/lib
    ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.19
    ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin
     
    WORKDIR $CATALINA_HOME
     
    EXPOSE 8080
     
    # 镜像运行容器就把tomcat启动起来
    CMD ["catalina.sh", "run"]
    

    3.2 docker build

    查看docker build使用方法

    docker build --help
    

    执行docker build -t (tag名)

    [root@localhost mydocker]# docker build -t zhang/tomcat:1.0 .               
    Sending build context to Docker daemon  198.4MB
    Step 1/11 : FROM centos
    latest: Pulling from library/centos
    a1d0c7532777: Pull complete 
    Digest: sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177
    Status: Downloaded newer image for centos:latest
     ---> 5d0da3dc9764
    Step 2/11 : MAINTAINER zhanglei
     ---> Running in df0dfb66a62d
    Removing intermediate container df0dfb66a62d
     ---> 1e7053949435
    Step 3/11 : ADD openjdk-11.0.2_linux-x64_bin.tar.gz /usr/local
     ---> 9b98a2af2ef3
    Step 4/11 : ADD apache-tomcat-9.0.19.tar.gz /usr/local
     ---> 513dc1c01353
    Step 5/11 : ENV JAVA_HOME /usr/local/jdk-11.0.2
     ---> Running in 91e95bd841be
    Removing intermediate container 91e95bd841be
     ---> 39c98b82022f
    Step 6/11 : ENV CLASSPATH .:$JAVA_HOME/lib
     ---> Running in f59e05ae989e
    Removing intermediate container f59e05ae989e
     ---> edc68b5e462c
    Step 7/11 : ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.19
     ---> Running in b22b8f0298a1
    Removing intermediate container b22b8f0298a1
     ---> 2841c3a092c9
    Step 8/11 : ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin
     ---> Running in f6ebcd63c8c2
    Removing intermediate container f6ebcd63c8c2
     ---> 6580c4b7e4e5
    Step 9/11 : WORKDIR $CATALINA_HOME
     ---> Running in 8af75ddd7f62
    Removing intermediate container 8af75ddd7f62
     ---> caedcd4bd116
    Step 10/11 : EXPOSE 8080
     ---> Running in b0353ea35616
    Removing intermediate container b0353ea35616
     ---> 27d1ab33db33
    Step 11/11 : CMD ["catalina.sh", "run"]
     ---> Running in 7281f2f1e31a
    Removing intermediate container 7281f2f1e31a
     ---> b0c823dc19cc
    Successfully built b0c823dc19cc
    Successfully tagged zhang/tomcat:1.0
    [root@localhost mydocker]# docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    zhang/tomcat        1.0                 b0c823dc19cc        9 seconds ago       556MB
    centos              latest              5d0da3dc9764        3 months ago        231MB
    gogs/gogs           latest              8ec7cc11f4a3        7 months ago        93.9MB
    

    运行容器

    docker run \
    --name zhang_tomcat \
    -p 8181:8080 \
    -d zhang/tomcat:1.0
    

    访问url,成功显示tomcat主页,创建镜像成功!

    B Dockfile指令详解

    参考资料:https://www.yuque.com/grasilife/docker/image-dockerfile-readme

    1 COPY 复制文件

    格式:

    • COPY <源路径>... <目标路径>
    • COPY ["<源路径1>",... "<目标路径>"]

    和 RUN 指令一样,也有两种格式,一种类似于命令行,一种类似于函数调用。

    COPY 指令将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置。比如:

    COPY package.json /usr/src/app/
    

    <源路径> 可以是多个,甚至可以是通配符,其通配符规则要满足 Go 的 filepath.Match 规则,如:

    COPY hom* /mydir/
    COPY hom?.txt /mydir/
    

    <目标路径> 可以是容器内的绝对路径,也可以是相对于工作目录的相对路径(工作目录可以用 WORKDIR 指令来指定)。
    目标路径不需要事先创建,如果目录不存在会在复制文件前先行创建缺失目录。

    此外,还需要注意一点,使用 COPY 指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等。
    这个特性对于镜像定制很有用。特别是构建相关文件都在使用 Git 进行管理的时候。

    2 ADD 更高级的复制文件

    ADD 指令和 COPY 的格式和性质基本一致。但是在 COPY 基础上增加了一些功能。

    比如 <源路径> 可以是一个 URL,这种情况下,Docker 引擎会试图去下载这个链接的文件放到 <目标路径> 去。
    下载后的文件权限自动设置为600,如果这并不是想要的权限,那么还需要增加额外的一层 RUN 进行权限调整,另外,如果下载的是个压缩包,需要解压缩,也一样还需要额外的一层 RUN 指令进行解压缩。
    所以不如直接使用 RUN 指令,然后使用 wget 或者 curl 工具下载,处理权限、解压缩、然后清理无用文件更合理。
    因此,这个功能其实并不实用,而且不推荐使用。

    如果 <源路径> 为一个 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,ADD 指令将会自动解压缩这个压缩文件到 <目标路径> 去。
    在某些情况下,这个自动解压缩的功能非常有用,比如官方镜像 ubuntu 中:

    FROM scratch
    ADD ubuntu-xenial-core-cloudimg-amd64-root.tar.gz /
    ...
    

    但在某些情况下,如果我们真的是希望复制个压缩文件进去,而不解压缩,这时就不可以使用 ADD 命令了。

    在 Docker 官方的 Dockerfile 最佳实践文档 中要求,尽可能的使用 COPY,因为 COPY 的语义很明确,就是复制文件而已,而 ADD 则包含了更复杂的功能,其行为也不一定很清晰。最适合使用 ADD 的场合,就是所提及的需要自动解压缩的场合。

    另外需要注意的是,ADD 指令会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。

    因此在 COPY 和 ADD 指令中选择的时候,可以遵循这样的原则,所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合使用 ADD。

    3 CMD 容器启动命令

    CMD 指令的格式和 RUN 相似,也是两种格式:

    • shell 格式:CMD <命令>
    • exec 格式:CMD ["可执行文件", "参数1", "参数2"...]
    • 参数列表格式:CMD ["参数1", "参数2"...]。在指定了 ENTRYPOINT 指令后,用 CMD 指定具体的参数。

    之前介绍容器的时候曾经说过,Docker 不是虚拟机,容器就是进程。
    既然是进程,那么在启动容器的时候,需要指定所运行的程序及参数。
    CMD 指令就是用于指定默认的容器主进程的启动命令的。

    在运行时可以指定新的命令来替代镜像设置中的这个默认命令,比如,ubuntu 镜像默认的 CMD 是 /bin/bash,如果我们直接 docker run -it ubuntu 的话,会直接进入 bash。
    我们也可以在运行时指定运行别的命令,如 docker run -it ubuntu cat /etc/os-release。
    这就是用 cat /etc/os-release 命令替换了默认的 /bin/bash 命令了,输出了系统版本信息。

    在指令格式上,一般推荐使用 exec 格式,这类格式在解析时会被解析为 JSON 数组,因此一定要使用双引号 ",而不要使用单引号。

    如果使用 shell 格式的话,实际的命令会被包装为 sh -c 的参数的形式进行执行。比如:

    CMD echo $HOME
    

    在实际执行中,会将其变更为:

    CMD [ "sh", "-c", "echo $HOME" ]
    

    这就是为什么我们可以使用环境变量的原因,因为这些环境变量会被 shell 进行解析处理。

    提到 CMD 就不得不提容器中应用在前台执行和后台执行的问题。这是初学者常出现的一个混淆。

    Docker 不是虚拟机,容器中的应用都应该以前台执行,而不是像虚拟机、物理机里面那样,用 upstart/systemd 去启动后台服务,容器内没有后台服务的概念。

    一些初学者将 CMD 写为:

    CMD service nginx start
    

    然后发现容器执行后就立即退出了。甚至在容器内去使用 systemctl 命令结果却发现根本执行不了。
    这就是因为没有搞明白前台、后台的概念,没有区分容器和虚拟机的差异,依旧在以传统虚拟机的角度去理解容器。
    对于容器而言,其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,从而退出,其它辅助进程不是它需要关心的东西。
    而使用 service nginx start 命令,则是希望 upstart 来以后台守护进程形式启动 nginx 服务。
    而刚才说了 CMD service nginx start 会被理解为 CMD [ "sh", "-c", "service nginx start"],因此主进程实际上是 sh。那么当 service nginx start 命令结束后,sh 也就结束了,sh 作为主进程退出了,自然就会令容器退出。
    正确的做法是直接执行 nginx 可执行文件,并且要求以前台形式运行。比如:

    CMD ["nginx", "-g", "daemon off;"]
    

    4 VOLUME 定义匿名卷

    • 格式为:VOLUME ["<路径1>", "<路径2>"...]
    • VOLUME <路径>
      之前我们说过,容器运行时应该尽量保持容器存储层不发生写操作,对于数据库类需要保存动态数据的应用,其数据库文件应该保存于卷(volume)中,后面的章节我们会进一步介绍 Docker 卷的概念。为了防止运行时用户忘记将动态文件所保存目录挂载为卷,在 Dockerfile 中,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据。
    VOLUME /data
    

    这里的 /data 目录就会在运行时自动挂载为匿名卷,任何向 /data
    中写入的信息都不会记录进容器存储层,从而保证了容器存储层的无状态化。当然,运行时可以覆盖这个挂载设置。
    比如:

    docker run -d -v mydata:/data xxxx
    

    在这行命令中,就使用了 mydata 这个命名卷挂载到了 /data 这个位置,替代了 Dockerfile 中定义的匿名卷的挂载配置。

    C 更新镜像

    1 进入指定容器伪终端

    [root@localhost mydocker]# docker ps
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                            NAMES
    25fae95b650c        zhang/tomcat:1.0    "catalina.sh run"        3 hours ago         Up 3 hours          0.0.0.0:8181->8080/tcp                           zhang_tomcat
    
    
    [root@localhost mydocker]# docker exec -it 25fae95b650c  /bin/bash
    [root@25fae95b650c apache-tomcat-9.0.19]# pwd
    /usr/local/apache-tomcat-9.0.19
    [root@25fae95b650c apache-tomcat-9.0.19]# ls
    BUILDING.txt  CONTRIBUTING.md  LICENSE  NOTICE  README.md  RELEASE-NOTES  RUNNING.txt  bin  conf  lib  logs  temp  webapps  work
    

    2 修改:这里复制了目录webapps,新目录名webapps_bak

    [root@25fae95b650c apache-tomcat-9.0.19]# cp -r webapps webapps_bak
    [root@25fae95b650c apache-tomcat-9.0.19]# ls
    BUILDING.txt  CONTRIBUTING.md  LICENSE  NOTICE  README.md  RELEASE-NOTES  RUNNING.txt  bin  conf  lib  logs  temp  webapps  webapps_bak  work
    [root@25fae95b650c apache-tomcat-9.0.19]# exit
    

    3 docker commit

    # 语法:docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
    # -a :提交的镜像作者;
    # -c :使用Dockerfile指令来创建镜像;
    # -m :提交时的说明文字;
    # -p :在commit时,将容器暂停。
    
    [root@localhost mydocker]# docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    zhang/tomcat        1.0                 b0c823dc19cc        3 hours ago         556MB
    centos              latest              5d0da3dc9764        3 months ago        231MB
    gogs/gogs           latest              8ec7cc11f4a3        7 months ago        93.9MB
    [root@localhost mydocker]# docker ps
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                            NAMES
    25fae95b650c        zhang/tomcat:1.0    "catalina.sh run"        3 hours ago         Up 3 hours          0.0.0.0:8181->8080/tcp                           zhang_tomcat
    
    [root@localhost mydocker]# docker commit -m='cp -r webapps webapps_bak' -a='zhanglei' 25fae95b650c zhang/tomcat:2.0
    sha256:f375fea412a39898806339339442b55d8ee8e21b4a5874e518abb84298b1f446
    [root@localhost mydocker]# docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    zhang/tomcat        2.0                 f375fea412a3        4 seconds ago       561MB
    zhang/tomcat        1.0                 b0c823dc19cc        3 hours ago         556MB
    centos              latest              5d0da3dc9764        3 months ago        231MB
    gogs/gogs           latest              8ec7cc11f4a3        7 months ago        93.9MB
    
  • 相关阅读:
    Ajax的工作原理
    ios 应用多语言自由切换实现
    开源码应用之Eclipse篇
    搜索引擎solr和elasticsearch
    字符串截取进阶
    nginx源代码分析--nginx模块解析
    C#网络编程系列文章(五)之Socket实现异步UDPserver
    mysql存储引擎的种类与差别(innodb与myisam)
    程序的记事本--log4net
    在海思hisiv100nptl平台上交叉编译并安装SRS
  • 原文地址:https://www.cnblogs.com/momolei/p/15712740.html
Copyright © 2020-2023  润新知