docker05-dockerfile

1.dockerfile是什么

Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。可以理解为docker自己的语言编写的脚本。

 

2.Dockerfile内容基础知识

1:每条保留字指令都必须为大写字母且后面要跟随至少一个参数

2:指令按照从上到下,顺序执行

3:#表示注释

4:每条指令都会创建一个新的镜像层,并对镜像进行提交

 

3.redis的dockerfile实例

https://hub.docker.com/_/redis/

FROM debian:buster-slim

# add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added
RUN groupadd -r -g 999 redis && useradd -r -g redis -u 999 redis

# grab gosu for easy step-down from root
# https://github.com/tianon/gosu/releases
ENV GOSU_VERSION 1.12
RUN set -eux; 
    savedAptMark="$(apt-mark showmanual)"; 
    apt-get update; 
    apt-get install -y --no-install-recommends ca-certificates dirmngr gnupg wget; 
    rm -rf /var/lib/apt/lists/*; 
    dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; 
    wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; 
    wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; 
    export GNUPGHOME="$(mktemp -d)"; 
    gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; 
    gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; 
    gpgconf --kill all; 
    rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; 
    apt-mark auto '.*' > /dev/null; 
    [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; 
    apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; 
    chmod +x /usr/local/bin/gosu; 
    gosu --version; 
    gosu nobody true

ENV REDIS_VERSION 6.0.15
ENV REDIS_DOWNLOAD_URL http://download.redis.io/releases/redis-6.0.15.tar.gz
ENV REDIS_DOWNLOAD_SHA 4bc295264a95bc94423c162a9eee66135a24a51eefe5f53f18fc9bde5c3a9f74

RUN set -eux; 
    
    savedAptMark="$(apt-mark showmanual)"; 
    apt-get update; 
    apt-get install -y --no-install-recommends 
        ca-certificates 
        wget 
        
        dpkg-dev 
        gcc 
        libc6-dev 
        libssl-dev 
        make 
    ; 
    rm -rf /var/lib/apt/lists/*; 
    
    wget -O redis.tar.gz "$REDIS_DOWNLOAD_URL"; 
    echo "$REDIS_DOWNLOAD_SHA *redis.tar.gz" | sha256sum -c -; 
    mkdir -p /usr/src/redis; 
    tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1; 
    rm redis.tar.gz; 
    
# disable Redis protected mode [1] as it is unnecessary in context of Docker
# (ports are not automatically exposed when running inside Docker, but rather explicitly by specifying -p / -P)
# [1]: https://github.com/redis/redis/commit/edd4d555df57dc84265fdfb4ef59a4678832f6da
    grep -E '^ *createBoolConfig[(]"protected-mode",.*, *1 *,.*[)],$' /usr/src/redis/src/config.c; 
    sed -ri 's!^( *createBoolConfig[(]"protected-mode",.*, *)1( *,.*[)],)$!102!' /usr/src/redis/src/config.c; 
    grep -E '^ *createBoolConfig[(]"protected-mode",.*, *0 *,.*[)],$' /usr/src/redis/src/config.c; 
# for future reference, we modify this directly in the source instead of just supplying a default configuration flag because apparently "if you specify any argument to redis-server, [it assumes] you are going to specify everything"
# see also https://github.com/docker-library/redis/issues/4#issuecomment-50780840
# (more exactly, this makes sure the default behavior of "save on SIGTERM" stays functional by default)
    
# https://github.com/jemalloc/jemalloc/issues/467 -- we need to patch the "./configure" for the bundled jemalloc to match how Debian compiles, for compatibility
# (also, we do cross-builds, so we need to embed the appropriate "--build=xxx" values to that "./configure" invocation)
    gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; 
    extraJemallocConfigureFlags="--build=$gnuArch"; 
# https://salsa.debian.org/debian/jemalloc/-/blob/c0a88c37a551be7d12e4863435365c9a6a51525f/debian/rules#L8-23
    dpkgArch="$(dpkg --print-architecture)"; 
    case "${dpkgArch##*-}" in 
        amd64 | i386 | x32) extraJemallocConfigureFlags="$extraJemallocConfigureFlags --with-lg-page=12" ;; 
        *) extraJemallocConfigureFlags="$extraJemallocConfigureFlags --with-lg-page=16" ;; 
    esac; 
    extraJemallocConfigureFlags="$extraJemallocConfigureFlags --with-lg-hugepage=21"; 
    grep -F 'cd jemalloc && ./configure ' /usr/src/redis/deps/Makefile; 
    sed -ri 's!cd jemalloc && ./configure !&'"$extraJemallocConfigureFlags"' !' /usr/src/redis/deps/Makefile; 
    grep -F "cd jemalloc && ./configure $extraJemallocConfigureFlags " /usr/src/redis/deps/Makefile; 
    
    export BUILD_TLS=yes; 
    make -C /usr/src/redis -j "$(nproc)" all; 
    make -C /usr/src/redis install; 
    
# TODO https://github.com/redis/redis/pull/3494 (deduplicate "redis-server" copies)
    serverMd5="$(md5sum /usr/local/bin/redis-server | cut -d' ' -f1)"; export serverMd5; 
    find /usr/local/bin/redis* -maxdepth 0 
        -type f -not -name redis-server 
        -exec sh -eux -c ' 
            md5="$(md5sum "$1" | cut -d" " -f1)"; 
            test "$md5" = "$serverMd5"; 
        ' -- '{}' ';' 
        -exec ln -svfT 'redis-server' '{}' ';' 
    ; 
    
    rm -r /usr/src/redis; 
    
    apt-mark auto '.*' > /dev/null; 
    [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; 
    find /usr/local -type f -executable -exec ldd '{}' ';' 
        | awk '/=>/ { print $(NF-1) }' 
        | sort -u 
        | xargs -r dpkg-query --search 
        | cut -d: -f1 
        | sort -u 
        | xargs -r apt-mark manual 
    ; 
    apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; 
    
    redis-cli --version; 
    redis-server --version

RUN mkdir /data && chown redis:redis /data
VOLUME /data
WORKDIR /data

COPY docker-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["docker-entrypoint.sh"]

EXPOSE 6379
CMD ["redis-server"]
View Code

 

4.dockerfile执行流程

(1)docker从基础镜像运行一个容器

(2)执行一条指令并对容器作出修改

(3)执行类似docker commit的操作提交一个新的镜像层

(4)docker再基于刚提交的镜像运行一个新容器

(5)执行dockerfile中的下一条指令直到所有指令都执行完成

 

5.dockerfile内容

1)FROM:基础镜像,当前新镜像是基于哪个镜像的

2)MAINTAINER:镜像维护者的姓名和邮箱地址

3)RUN:镜像构建容器时会运行此条命令

4)EXPOSE:当前容器对外暴露出的端口

5)WORKDIR:指定在创建容器后,终端登陆的进来默认工作目录,就像进入centos默认容器是在根目录/这里

6)ENV:用来在构建镜像过程中设置环境变量,这个环境变量可以在后续的任何RUN指令中使用,也可以在其它指令中直接使用这些环境变量
7)ADD:将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包

8)COPY:类似ADD,拷贝文件和目录到镜像中。将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置

9)VOLUME:容器数据卷,用于数据保存和持久化工作

10)CMD:指定一个容器启动时要运行的命令,Dockerfile 中可以有多个 CMD 指令,最终只有最后一个生效,CMD 会被 docker run 之后的参数替换

11)ENTRYPOINT :指定一个容器启动时要运行的命令,docker run -it id /bin/bash,这里后面接了命令/bin/bash,对于/bin/bash命令不会覆盖ENTRYPOINT 的目录而是追加,但是会覆盖CMD的命令

12)ONBUILD:当构建一个被继承的Dockerfile时会运行此条命令

 

6.示例

6.1示例1

1)编辑dockerfile文件

FROM centos:6.8
MAINTAINER zzyy<zzyy167@126.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN ls -la
EXPOSE 80
CMD echo $MYPATHCMD echo "success--------------ok"
CMD /bin/bash

命令说明

FROM centos:6.8                  继承自centos:6.8 
MAINTAINER zzyy<zzyy167@126.com>    作者和邮箱
ENV MYPATH /usr/local           定义环境变量MYPATH = /usr/local 
WORKDIR $MYPATH              进入容器后的默认目录/usr/local 
RUN ls -la                 运行RUN命令创建容器时,会执行命令 ls -la
EXPOSE 80                  对外暴露端口80
CMD echo $MYPATHCMD echo "success--------------ok"   执行命令 打印字符串
CMD /bin/bash

 

2)build生成新的镜像

可以看到 la -la执行了  打印字符串也执行了

最终成功生成新的镜像

 

3)使用新生成的镜像创建运行容器

进入容器,运行命令pwd查看当前目录,发现当前目录是/usr/local,说明配置生效了

 

 

4)小结

上面已涉及到了命令:FROM 、MAINTAINER 、ENV 、WORKDIR 、RUN 、EXPOSE 、CMD

 

6.2示例2-CMD和ENTRYPOINT的不同

6.2.1CMD

1)创建dockerfle

里面就一个ls命令

FROM centos:6.8
CMD ls

 

2)build创建新的镜像

 

3)使用镜像创建运行容器

ls命令执行了

 

4)使用镜像创建运行容器并追加命令

这样子执行相当于dockerfile是下面这样

FROM centos:6.8
CMD ls
CMD -la

加了一条命令 -la

由于-la不是命令,所以执行出错了

 

6.2.2ENTRYPOINT

1)dockerfile

FROM centos:6.8
ENTRYPOINT ls

 

2)build创建新镜像

 

3)创建和启动容器

执行了命令 ls

 

4)使用镜像创建运行容器并追加命令

这样子执行相当于dockerfile是这样子

FROM centos:6.8
ENTRYPOINT ls -la

ls和-la命令拼接起来了

这就是CMD和ENTRYPOINT 的区别

 

6.2示例3-ONBUILD

6.2.1父镜像

1)dockerfile

FROM centos:6.8
ONBUILD RUN echo "bei ji chengle 666666"

ONBUILD:当这个dockerfile生成的镜像被继承的时候,会打印这段文字

 

2)build

 

6.3.2子镜像

1)dockerfile

FROM zzyy/mycentos:4.2
RUN echo "run---qidong"

继承自上面生成的镜像:zzyy/mycentos:4.2

 

2)build

由于它继承自zzyy/mycentos:4.2,所以build的时候打印了父镜像zzyy/mycentos:4.2的dockerfile里面ONBUILD要打印的字符串

 

 

6.3带有JAVA、TOMCAT环境的centos

1)dockerfile

FROM  centos
MAINTAINER    zzyy<zzyybs@126.com>
#把宿主机当前上下文的c.txt拷贝到容器/usr/local/路径下
COPY c.txt /usr/local/cincontainer.txt
#把java与tomcat添加到容器中 从宿主机复制jdk和tomcat到容器的usr/local目录下
ADD jdk-8u171-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.8.tar.gz /usr/local/
#安装vim编辑器
RUN yum -y install vim
#设置工作访问时候的WORKDIR路径,登录落脚点
ENV MYPATH /usr/local
WORKDIR $MYPATH
#配置java与tomcat环境变量
ENV JAVA_HOME /usr/local/jdk1.8.0_171
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.8
ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.8
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
#容器运行时监听的端口
EXPOSE  8080
#启动时运行tomcat并且打印日志
# ENTRYPOINT ["/usr/local/apache-tomcat-9.0.8/bin/startup.sh" ]
# CMD ["/usr/local/apache-tomcat-9.0.8/bin/catalina.sh","run"]
CMD /usr/local/apache-tomcat-9.0.8/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.8/bin/logs/catalina.out

2)build

  dodker build -f /usr/local/docker/Dockerfile -t zzyytomcat9 .

3)run

 docker run -d -p 9080:8080 --name myt9 -v /zzyyuse/mydockerfile/tomcat9/test:/usr/local/apache-tomcat-9.0.8/webapps/test -v /zzyyuse/mydockerfile/tomcat9/tomcat9logs/:/usr/local/apache-tomcat-9.0.8/logs --privileged=true zzyytomcat9

在tomcat的webapp目录下创建了两个容器数据卷,相当于两个项目,这样子可以在宿主机下直接对项目进行修改,容器下项目会同步

 

 
 

原文地址:https://www.cnblogs.com/jthr/p/15158497.html