社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  docker

如何用 Dockerfile 构建镜像

生信菜鸟团 • 5 年前 • 748 次点击  

我们除了通过 commit 的方式来构建 docker 镜像外,Dockerfile 是另一种构建镜像的方式。Dockerfile是一个文本文件,里面包含了打包 docker 镜像所需要用到的所有命令,这样,docker 就可以通过读取 Dockerfile 里面的命令来自动化地构建 docker 镜像。相比于 commit,使用Dockerfile的好处在于其生成镜像的方式更加透明,我们可以一目了然地知道这个镜像是如何一步步生成的,同时构建的镜像也相对较小,文本的形式也方便镜像的管理与复用。

使用 DockerFile 创建镜像

先来复习下,之前我们是如何通过docker commit生成一个新镜像的:

具体过程见:我的 Docker 笔记

Step 1:首先,我们需要启动一个容器,当我们运行镜像并生成容器时,会在基础镜像的顶部添加新的可写层「容器层」;

Step 2:我们会对容器执行一些操作(比如安装软件)。我们对容器所做的所有更改都将写入此可写容器层,每一个操作都会在上面累加一层,每一层都是前一层变化的增量;

Step 3:执行 docker commit  来基于已有的容器创建一个新的镜像。

DockerFile其实执行的是相同的步骤。第一步,我们需要使用FROM命令指定一个基础镜像生成一个容器,然后用一些「镜像操作指令」对容器做一些修改。最后用docker build命令来生成镜像。

Dockerfile常用指令

类型命令
基础镜像信息FROM
维护者信息MAINTAINER
镜像操作指令 RUN、COPY、ADD、EXPOSE、WORKDIR、ONBUILD、USER、VOLUME等
容器启动时执行指令CMD、ENTRYPOINT

最简单的Dockerfile比如这样:

FROM ubuntu:18.04
COPY . /app
RUN make /app
CMD python /app/app.py

意思就是,使用FROM命令先从 ubuntu:18.04 基础镜像创建一个容器,接着用COPY命令向容器中的/app文件夹拷贝宿主机当前目录的文件,使用RUN命令,执行make安装软件。CMD命令指定容器启动时需要执行的命令。

创建完 DockerFile,我们就可以使用docker build来创建镜像了。

docker build -t test:v1.0 .

执行命令后,控制台会逐层输出构建内容,直到输出两个 Successfully 即为构建成功。

Successfully built 93a111d8c6e5
Successfully tagged test:v1.0

常用 Dockerfile 指令详解

FROM

指定创建镜像时的基础镜像。

FROM <image>  [AS <name>


    
]
或者
FROM <image>[:<tag>]  [AS <name>]
或者
FROM <image>@<digest> [AS <name>]

Dockerfile的第一条命令必须为FROM指令,其中 [AS ] 为指定一个名称。

RUN

RUN 指令用于执行命令(比如安装软件),每一次RUN都会在之前的基础上产生新的一层,并把执行后的结果提交。因此,我们在使用 RUN 时应该尽可能的把要执行的命令一次写完,以减少最后生成的镜像层数,避免镜像过于臃肿。

RUN <command>
或者
RUN ["executable","param1","param2"]

为了把所有需要的命令写到一个RUN中,我们通常需要用到换行符\:

RUN apt-get update \
  && apt-get install -y --no-install-recommends \
    file \
    git \
    libapparmor1 \
    libcurl4-openssl-dev \
    libedit2 \
    libssl-dev \
    lsb-release \
    multiarch-support \
    psmisc \
    procps \
    python-setuptools \
    sudo \
    wget \
    libclang-dev \
  && wget -O libssl1.0.0.deb http://ftp.debian.org/debian/pool/main/o/openssl/libssl1.0.0_1.0.1t-1+deb8u8_amd64.deb \
  && dpkg -i libssl1.0.0.deb \
  && rm libssl1.0.0.deb \
  && if [ -z "$RSTUDIO_VERSION" ]; then RSTUDIO_URL="https://www.rstudio.org/download/latest/stable/server/debian9_64/rstudio-server-latest-amd64.deb"else RSTUDIO_URL="http://download2.rstudio.org/rstudio-server-${RSTUDIO_VERSION}-amd64.deb"fi \
  && wget -q $RSTUDIO_URL \
  && dpkg -i rstudio-server-*-amd64.deb \

ADD

ADD 可以复制新文件,目录,远程文件到容器中。其中  可以为文件(要复制的文件必须和Dockerfile位于同一目录下),目录,URL;可以是镜像内绝对路径,或者相对于工作目录的相对路径。

ADD <src>...  <dest>

COPY

COPY 与 ADD 的功能十分类似,但 COPY 只支持本地的文件以及目录的复制,不像 ADD 指令可以远程获取文件并解压。

COPY <src> <dest>

CMD

指定启动容器时默认执行的命令。

CMD command param1 param2
或者
CMD ["executable","param1","param2"]

每个Dockerfile中只能有一条CMD命令,如果指定了多条命令,只有最后一条被执行,如果用户启动容器时手动指定了运行的命令,则会覆盖掉CMD指定的命令。比如设置在容器启动时进入 bash。

CMD /bin/bash
# 或者
CMD ["/bin/bash"]

MAINTAINER

MAINTAINER用于指定作者。

MAINTAINER <name> 


    
<email>

EXPOSE

EXPOSE 指令用于告诉 Docker 容器监听的特殊端口,但是此时端口还没有暴露给宿主机,只有在运行容器用参数-p 时才会暴露端口。

EXPOSE <port> [<port>/<protocol>...]

WORKDIR

WORKDIR 命令用于设置 RUNCMDENTRYPOINTCOPYADD 等指令的工作目录,类似cd的意思,进入目录。

WORKDIR /path/to/workdir

ENTRYPOINT

ENTRYPOINT的作用和CMD一样,但这个命令会在启动容器时作为根命令执行,不会被覆盖。

ENTRYPOINT command param1 param2
# 或者
ENTRYPOINT ["executable","param1","param2"]

LABEL

用于为镜像指定标签,可用 docker inspect 命令查看,用来镜像以后被搜索的时候用。

LABEL <key>=<value> <key>=<value> ...

VOLUME

VOLUME 指令用于为容器创建一个挂载点,这个挂载点可以用来挂载 本地文件/文件夹 也可以用来挂载 数据卷。其中若在启动一个新容器时没有指定挂载目录,则会自动创建一个数据卷,当容器被销毁时,数据卷如果没有被其它容器引用则会被删除。

VOLUME ["/data1","/data2"]

USER

指定运行容器的用户以及用户组。默认为 root 用户,所以当服务不需要管理员权限时,可以通过该命令指定运行用户。

USER [:]

ENV

ENV 指令用于设定环境变量,容器运行的时候这个变量也会保留。

ENV <key> <value> 或 ENV <key>=


    
<value> ...

这些环境变量可以在运行时被docker run --env =覆盖掉。

ARG

定义创建镜像过程中使用的变量。

ARG  [=<default value>]

在执行docker build时,也可以通过-duild-arg[=]来为变量赋值;镜像编译成功之后,ARG指定的变量不再存在(ENV指定的仍然在镜像中保留)。

参考

  • https://docs.docker.com/engine/reference/builder/

  • https://docs.docker.com/develop/develop-images/dockerfile_best-practices/

号外:(南京、南宁见!)全国巡讲第17-18站(生信入门课加量不加价)

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/46618
 
748 次点击