前言
这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战
本文主要讲述Dockerfile的基本使用,简单地说,DockerFile其实就是一个脚本,把我们需要执行的指令都汇总到一起而已。
基本示例
在讲解Dockerfile的基本命令前,我先以 使用Flask框架构建Http服务器 为例,说明Dockerfile的基本用法。
1.目录结构:
.
├── Dockerfile
└── docker-test
├── flask_server.py
└── requirements.txt
2.Dockerfile文件内容:
# 指定基础镜像
FROM python:3
# 标明作者
LABEL author="yangan"
# 设置工作目录,即进入容器后的默认路径
WORKDIR /data/docker-test
# 将宿主机的docker-test目录的内容拷贝到容器
ADD ./docker-test /data/docker-test
# 安装Python依赖
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
# 暴露端口
EXPOSE 10086
# 设置环境变量
ENV PYTHONIOENCODING=utf-8
# 执行Python脚本
CMD [ "python", "./flask_server.py" ]
3.flask_server.py 内容:
from flask import Flask
app = Flask(__name__)
@app.route('/', methods=['GET'])
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=10086, debug=True)
4.requirements.txt内容:
Click==7.0
Flask==1.1.1
itsdangerous==1.1.0
Jinja2==2.10.3
MarkupSafe==1.1.1
Werkzeug==0.16.0
5.根据Dockerfile创建镜像(注意有个点,代表当前目录):
docker build -t docker-test:v1 .
打包时的效果图
打包成功效果图
Dockerfile命令
FROM
语法:FROM
<name>
该指令的作用是指定基础镜像。
在看其他人的Dockerfile时,我们可能会看到alpine版的镜像。为什么使用这个版本呢?以Ubuntu镜像为例,如果是普通的镜像,比如ubuntu:16.04,通常需要占几百M;而alpine版的镜像,比如ubuntu:alpine,只需要几十M,从镜像大小的角度看,alpine版的镜像是非常有优势的,但是凡事还是要看适用场景,如果你构建的镜像只运行单个服务,则使用 alpine版镜像 可能更好,如果需要运行多个服务,则使用普通版镜像更好,因为库更全,安装更顺手,具体区别可参见这里
MAINTAINER
语法:MAINTAINER
<name>
该指令的作用是说明镜像制作者
WORKDIR
语法:WORKDIR
<dir>
指定工作目录,即进入容器后的路径,相当于进入容器后执行cd <dir>
ENV
语法:ENV
<key>=<value>
指定环境变量,以此镜像创建的容器都会应用这些环境变量。
创建普通环境变量:ENV PYTHONIOENCODING=utf-8,相当于 export PYTHONIOENCODING=utf-8
创建PATH环境变量:ENV PATH="/root/.local/bin:${PATH}",相当于 export PATH="/root/.local/bin:${PATH}",在安装JDK时比较常用到。
注意这里有个陷阱,即 /root/.local/bin 必须使用绝对路径,且不能掺杂环境变量,如 $HOME/.local/bin,这样设置是无效的。
另一种设置环境变量的方式(不推荐):
# 1.首先写入到文件
echo 'export PATH="$PATH:/root/.local/bin"' >> ~/.bashrc
# 2.执行命令时先使用source命令使环境变量生效
docker exec -it ubuntu_test bash -c "source ~/.bashrc && make proto"
EXPOSE
语法:EXPOSE
<port> [<port>...]
声明运行时容器提供服务端口
声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口的服务。 这个命令并不能像docker-compose一样绑定宿主机端口,因为docker-compose是直接生成容器,Dockerfile只是生成一个镜像,端口的绑定需在启动容器时进行。
VOLUME
语法:VOLUME
["<mountpoint>"]
在镜像内创建挂载点,并不会在宿主机创建挂载点,宿主机的挂载点是自动生成的。
既然需要在启动时才能绑定宿主机端口或者挂载宿主机某个目录, 那么还有必要在Dockerfile指定吗? www.cnblogs.com/51kata/p/52…
ADD & COPY
# 语法
ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"] (这种方式路径间需要有空格)
COPY命令:
COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"] (这种方式路径间需要有空格)
1.如果<src>是文件且<dest>中不使用斜杠结束,则会将<dest>视为文件,<src>的内容会写入<dest>。
2.如果<src>是文件且<dest>中使用斜杠结束,则会<src>文件拷贝到<dest>目录下。
3.如果<src>是目录, 则会将src目录的文件到容器dest目录,注意并不会拷贝src这个目录。
共同点:
- 1.拷贝文件(只能拷贝上下文内的文件)
- 2.可通过chown控制文件属性,如果没有该选项,拷贝的文件或文件夹默认属于root用户(uid和gid为0)
不同点:
- COPY能把前一阶段构建的产物拷贝到另一个镜像中(multistage 场景)
- ADD命令能解压压缩文件并把它们添加到镜像中
- ADD命令能将远程文件拷贝到镜像中,类似wget
# 解压举例
WORKDIR /app
ADD test.tar.gz .
# 远程拷贝举例
ADD http://example.com/big.tar.xz /app
注意点:
1.绝对路径和相对路径
COPY test relativeDir/ # adds "test" to
WORKDIR/relativeDir/ COPY test /absoluteDir/ # adds "test" to /absoluteDir/
2.chown选项只对Linux系统有效
RUN
语法:
RUN <command> (在Linux下默认在/bin/sh执行)(shell form)
RUN ["executable", "param1", "param2"] (exec form)
执行命令的指令,后面接执行的命令,比如 RUN apt-get update
1.每次执行RUN命令,都会新建一个新的镜像层,为了减少镜像层的数量,一般都会将多条命令写在一起。
2.使用其他shell
RUN /bin/bash -c 'echo hello'
RUN ["/bin/bash", "-c", "echo hello"]
3.RUN ["executable", "param1", "param2"] 这种形式的RUN命令,参数必须用双引号包裹,因为解析的时候是被解析成JSON数组
4.RUN ["executable", "param1", "param2"] 这种形式的RUN命令, 注意 RUN [ "echo", "$HOME" ] 和 RUN [ "sh", "-c", "echo $HOME" ]并不一样, RUN [ "echo", "$HOME" ]并不会调用shell,所以不会寻找环境变量。
CMD
语法:
CMD ["executable","param1","param2"] (exec form, this is the preferred form)
CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
CMD command param1 param2 (shell form)
1.容器启动时执行的命令,但是一个Dockerfile中只能有一条CMD命令,多条则只执行最后一条CMD。
2.CMD主要用于容器时启动指定的服务,当Docker run command的命令匹配到CMD command时,会替换CMD执行的命令。
3.CMD 与 RUN并不一样, RUN命令执行时会生成一个新的镜像层,而CMD只是单纯执行命令而已
4.一个Dockerfile中只能有一条CMD命令,多条则只执行最后一条CMD.
5.exec form 形式的CMD命令,依然不会调用shell,与RUN命令一样。
参考
Dokcerfile官方文档
Docker Dockerfile 定制镜像
docker之Dockerfile实践
Docker设置PATH环境变量