docker05-dockerfile

1.dockerfile是什么

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

 

2.Dockerfile内容基础知识

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

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

3:#表示注释

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

 

3.redis的dockerfile实例

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

docker05-dockerfile
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( *,.*[)],)$!\10\2!‘ /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

docker05-dockerfile

命令说明

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执行了  打印字符串也执行了

docker05-dockerfile

最终成功生成新的镜像

 

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

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

docker05-dockerfile

 

 

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

docker05-dockerfile

 

2)build创建新的镜像

docker05-dockerfile

 

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

ls命令执行了

docker05-dockerfile

 

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

docker05-dockerfile

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

FROM centos:6.8
CMD ls
CMD -la

加了一条命令 -la

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

 

6.2.2ENTRYPOINT

1)dockerfile

FROM centos:6.8
ENTRYPOINT ls

docker05-dockerfile

 

2)build创建新镜像

docker05-dockerfile

 

3)创建和启动容器

执行了命令 ls

docker05-dockerfile

 

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

docker05-dockerfile

这样子执行相当于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"

docker05-dockerfile

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

 

2)build

docker05-dockerfile

 

6.3.2子镜像

1)dockerfile

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

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

docker05-dockerfile

 

2)build

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

docker05-dockerfile

 

 

 

 

 
 

docker05-dockerfile

上一篇:[ICPC2014 WF] F Messenger 题解


下一篇:mybatis 自定义TypeHandler