Skip to main content

Dockerfile 构建镜像

如果使用 docker commit 来提交和分享镜像,别人只能通过 registry 或其它方式导入镜像,不仅不方便,而且不知道镜像如何制作,可能有不安全因素。而通过 Dockerfile 构建镜像,只需分享 Dockerfile 即可分享镜像,别人可以根据 Dockerfile 构建一个一样的镜像。

Dockerfile 指令​

通常将 Dockerfile 文件命名为 Dockerfile,也可以使用其它名字,但构建的时候需要指定 Dockerfile 文件。指令通常写为大写,虽然小写也可以使用。

FROM​

定义 base image

为了安全。尽量使用官方 base image

FROM scratch
FROM centos
FROM Ubuntu:20.04

LABEL​

定义 metadata ,类似注释

LABEL maintainer="[email protected]"
LABEL version="1.0"
LABEL description="xx"

WORKDIR​

设定当前目录,类似 cd ,如果不存在会自动创建。尽量使用 WORKDIR ,不要用 RUN cd ,尽量用绝对目录

WORKDIR /root

ADD​

复制文件,如果是压缩文件会自动解压缩

# 复制 hello 到根目录
ADD hello /
# 压缩文件会被解压缩
ADD test.tar.gz /

如果是相对路径,会是 WORKDIR 的相对路径

WORKDIR /root
ADD hello test/
# /root/test/hello

ENV​

设置环境变量、常量,可以通过 $ 引用

ENV MYSEQL_VERSION5.6
RUN apt install -y mysql-server="${MYSQL_VERSION}" \
&& rm -rf /var/lib/apt/lists/*

RUN​

运行命令并创建新的 image layer 。避免无用分层,合并多个命令为一行。对于复杂的命令,可以使用反斜杠换行,以便美观。

RUN apt update && apt install -y perl \
rm -rf /var/lib/apt/lists/*

CMD​

设置容器启动后默认执行的命令和参数。定义多个 CMD ,只有最后一个执行。如果 docker run 指定了其它命令, CMD 会被忽略,例如 docker run -it image_name /bin/bash ,则 CMD 不会执行。

EXPOSE 27017
CMD ["mongod"]

ENTRYPOINT​

使用较多。设置容器启动时运行的命令。让容器以应用程序或服务的形式运行。不会被忽略。最佳实践:写一个 shell 脚本作为 entrypoint

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

Shell 格式和 Exec 格式

  • Shell 格式
# Shell 
RUN apt install -y vim
CMD echo "hello"
ENTRYPOINT echo "hi"
  • Exec 格式
# Exec
RUN [ "apt" , "install" , "-y" , "vim"]
CMD [ "/bin/echo" , "hello" ]
EMTRYPOINT [ "/bin/echo" , "hi" ]

Shell 格式可以使用 $ 引用变量,而 Exec 不行。

FROM centos
EMV name Jim
# 成功转义
CMD echo "hello $name"
# 不成功转义
ENTRYPOINT ["/bin/echo","hello $name"]
# 成功转义
ENTRYPOINT ["bin/bash","-c","echo hello $name"]

Dockerhub​

类似 GitHub ,用来分享自己的 image ,

https://hub.docker.com

命令行登录 , docker login ,输入用户名和密码登录。

push 命令,类似 git push

docker push [OPTIONS] NAME[:TAG]
docker push wjftu/helloworld:latest

发布 image ,别人不知道 image 是怎么产生的,有没有安全问题,因此发布 image 不如发布 Dockerfile ,可以使用 create -> create automated build 来使用 GitHub 或 Bitbucket 仓库的 Dockerfile 来构建。

构建镜像实例​

FROM python:3.10
LABEL maintainer="wjf<[email protected]>"
RUN pip --trusted-host=pypi.python.org --trusted-host=pypi.org --trusted-host=files.pythonhosted.org install flask
COPY app.py /app/
WORKDIR /app
EXPOSE 5000
CMD ["python" , "app.py"]

使用命令 docker build -t wjftu/hello-flask . 构建,末尾的点表示 Dockerfile 在当前路径且名称为默认。

Step 1/7 : FROM python:3.10
---> cecf555903c6
Step 2/7 : LABEL maintainer="wjf<[email protected]>"
---> Using cache
---> 3c18f2523dba
Step 3/7 : RUN pip --trusted-host=pypi.python.org --trusted-host=pypi.org --trusted-host=files.pythonhosted.org install flask
---> Using cache
---> 8f9112836ef7
Step 4/7 : COPY app.py /app/
---> 4946666a6b8a
Step 5/7 : WORKDIR /app
---> Running in 0613b3125b62
Removing intermediate container 0613b3125b62
---> edcbf86421f4
Step 6/7 : EXPOSE 5000
---> Running in 44abba67cf7c
Removing intermediate container 44abba67cf7c
---> 9ff81a193f1f
Step 7/7 : CMD ["python" , "app.py"]
---> Running in 8f9f0165f09e
Removing intermediate container 8f9f0165f09e
---> 0070c7e85303
Successfully built 0070c7e85303
Successfully tagged wjftu/hello-flask:latest

可以看到 build 的 image

root@instance-20210531-1826:~/py# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
wjftu/hello-flask latest 0070c7e85303 7 minutes ago 928MB

如果在 build 的时候遇到问题,可以进入 build 时的临时容器查看。

 ---> 8f9112836ef7
Step 4/7 : COPY app.py /app
---> 727ded8b2327
Step 5/7 : WORKDIR /app
Cannot mkdir: /app is not a directory

进入容器

docker run -it 727ded8b2327 /bin/bash