社区所有版块导航
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

Docker之Dockerfile文件指令说明

code泷 • 5 年前 • 488 次点击  
阅读 75

Docker之Dockerfile文件指令说明

Dockerfile是一个用来构建镜像的文本文件,里面包含了指令,配置,环境,环境变量等等信息。

查看镜像的Dockerfile

打开https://hub.docker.com/网页,搜索想要查找的镜像。

image-20210117095346227

这就是mysql8的Dockerfiel文件内容

github.com/docker-libr…

image-20210117095506100

Dockerfile指令说明

FROM

位于Dockerfile开头,表示基于什么镜像构建。

# 语法:FROM <基础镜像>
# 例如:
FROM centos  # 表示基于centos开始构建镜像
FROM openjdk:8-jdk-alpine  # 表示基于openjdk开始构建镜像
复制代码

LABEL

Dockerfile的元数据,描述作用。

# 语法:LABEL <key>=<value> <key>=<value> <key>=<value> ...
# 例如:
LABEL version="1.0" author="codelong" description="dockerfile demo"
复制代码

RUN

运行命令,每次run都会生成一个图层,所以最好将命令合并执行,有以下俩种格式:

shell格式:

# 语法:RUN <命令行命令>
# <命令行命令> 等同于,在终端操作的 shell 命令。 
# 例如:
RUN yum -y update \	# '\'代表换行
    && yum install -y vim	# '&&'代表合并多条
复制代码

exec格式:

# 语法:RUN ["可执行文件", "参数1", "参数2"]
# 例如:
RUN ["/bin/bash", "-c", "echo hello"] 等价于 RUN /bin/bash -c echo hello
复制代码

WORKDIR

用于指定工作目录,切换路径。

docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。

WORKDIR /code # 没有则自动创建code目录
WORKDIR demo
RUN pwd
复制代码

输出 /code/demo。

最好不要用RUN cd来切换目录,而使用WORKDIR,这样可以减少不必要的图层,尽量使用绝对目录。

ADD &COPY

ADD和COPY都可以将构建环境中的文件或目录复制到镜像中。

# 语法:ADD <当前主机的文件或目录> <容器内部的文件或路径>
# 例如:
WORKDIR /demo
ADD data.txt code/data.txt
复制代码
# 语法:COPY <当前主机的文件或目录> <容器内部的文件或路径>
# 例如:
WORKDIR /demo
COPY data.txt code/data.txt
复制代码

最终都会将data.txt文件添加到/demo/code/目录下。

区别:

  1. ADD 添加的文件是压缩文件的话,会自动解压。
  2. COPY 只能复制构建目录下的文件,ADD可以添加一个构建上下文中的文件或目录,也可以是一个URL。
ADD https://www.baidu.com/data.zip /
复制代码

ENV

这个指令很简单,就是设置环境变量,无论是后面的其它指令,如 RUN,还是运行时的应用,都可以直接使用这里定义的环境变量。它有如下两种格式:

# 语法1:ENV <key> <value>
# 语法2:ENV <key1>=<value1> <key2>=<value2>...
# 例如:
ENV MYSQL_VERSION 1.12
ENV GOSU_VERSION=1.12 JAVA_HOME=/app/jdk1.8/

#RUN使用环境变量
RUN echo "${JAVA_HOME}"
复制代码

CMD

类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:

  • CMD 在docker run 时运行。
  • RUN 是在 docker build。

作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。

注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。

# 语法1:CMD <shell 命令> 
# 语法2:CMD ["<可执行文件或命令>","<param1>","<param2>",...] 
# 语法3:CMD ["<param1>","<param2>",...]  # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数
复制代码

ENTRYPOINT

类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。

但是, 如果运行 docker run 时使用了 --entrypoint 选项,此选项的参数可当作要运行的程序覆盖 ENTRYPOINT 指令指定的程序。

优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。

注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。

# 语法:ENTRYPOINT ["<executeable>","<param1>","<param2>",...]
复制代码

可以搭配 CMD 命令使用:一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参,以下示例会提到。

示例:

假设已通过 Dockerfile 构建了 nginx:test 镜像:

FROM nginx

ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参 
复制代码

1不传参运行 docker run nginx:test

容器内会默认运行以下命令,启动主进程。

nginx -c /etc/nginx/nginx.conf
复制代码

2传参运行 docker run nginx:test -c /etc/nginx/new.conf

容器内会默认运行以下命令,启动主进程(/etc/nginx/new.conf:假设容器内已有此文件)

nginx -c /etc/nginx/new.conf
复制代码

VOLUME

该指令使容器中的一个目录具有持久化存储的功能,该目录可被容器本身使用,也可共享给其他容器。当容器中的应用有持久化数据的需求时可以在Dockerfile中使用该指令。如 VOLUME /tmp 这里的 /tmp 目录就会在运行时自动挂载为匿名卷,任何向 /tmp 中写入的信息都不会记录进容器存储层,从而保证了容器存储层的无状态化。当然,运行时可以覆盖这个挂载设置。比如:docker run -d -v mydata:/tmp xxxx

EXPOSE

仅仅只是声明端口。

作用:

  • 帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。
  • 在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。
  • 要将 EXPOSE 和在运行时使用 -p <宿主端口>:<容器端口> 区分开来。-p,是映射宿主端口和容器端口,换句话说,就是将容器的对应端口服务公开给外界访问,而 EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行端口映射。

Shell和Exec格式说明

在Dockerfile中,命令的写法有Shell格式和Exec格式:

Shell格式的Dockerfile如下:

RUN apt-get install -y vim
CMD echo "hello world"
ENTRYPOINTT echo "hello world"
复制代码

Exec格式如下所示:

RUN ["apt-get","install","-y","vim"]
CMD ["/bin/echo","hello world"]
ENTRYPOINTT ["/bin/echo","hello world"]
复制代码

在使用Exec格式的时候需要注意和常量的搭配使用问题,比如在Shell格式下:

FROM ubuntu
ENV name codelong
ENTRYPOINTER echo "hello $name"
复制代码

创建镜像,运行容器后输出:hello codelong。

但是在Exec格式下:

FROM ubuntu
ENV name codelong
ENTRYPOINTER ["/bin/echo","hello $name"]
复制代码

创建镜像,运行容器后输出:hello $name。

正确的写法是:

FROM ubuntu
ENV name codelong
ENTRYPOINTER ["/bin/bash","-c","echo hello $name"]
复制代码
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/106272