在实际开发中完全使用他人构造好的镜像是不现实的。
所以本篇文章我们将会学习Dockerfile的知识,从而学习如何构造符合项目要求的镜像。
本文保留 2020 年 Ubuntu 16.04/Python 环境的示例;新项目请使用受支持的基础镜像,并验证依赖版本。下面重点介绍 Dockerfile 指令的含义。
Dockerfile文档展示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 FROM ubuntu:16.04 RUN apt-get update -y && \ apt-get install -y python3-pip python3-dev # We copy just the requirements.txt first to leverage Docker cache COPY ./requirements.txt /app/requirements.txt WORKDIR /app RUN python3 -m pip install --upgrade pip RUN pip3 install -r requirements.txt COPY . /app # ENTRYPOINT [ "python3" ] CMD [ "python3", "main.py" ]
逐行命令解释
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 1. FROM ubuntu:16.04 FROM 关键字会初始化一个image构造,并为后续的所有操作设置基础镜像,,上面的例子表示,该image是以ubuntu:16.04为基础构建的。 2. RUN apt-get update -y && \ apt-get install -y python3-pip python3-dev RUN 会在上一层的基础上添加新的layer,并将结果提交给下一层。RUN命令有两种形式。一种是shell格式,格式如下 RUN <command> (shell form, the command is run in a shell, which by default is /bin/sh -c on Linux or cmd /S /C on Windows) 另一种是exec格式,格式如下 RUN ["executable", "param1", "param2"] (exec form) && 是 shell 的条件连接符:前一条命令成功才执行后一条;\ 用于续行。将两条命令放在同一个 RUN 中,会形成同一层的文件系统变更;两个 RUN 则分别构建。 3. COPY ./requirements.txt /app/requirements.txt COPY 命令同样有两种形式,可以实现将源文件复制到目标位置,支持按 Go filepath.Match 规则匹配的通配符(glob),不是正则表达式。 COPY [--chown=<user>:<group>] <src>... <dest> COPY [--chown=<user>:<group>] ["<src>",... "<dest>"] 4. WORKDIR /app - WORKDIR 会设置当前的工作目录,之后的 RUN、CMD、ENTRYPOINT 使用这个工作目录,COPY 和 ADD 的相对目标路径也以它为基准;COPY/ADD 的本地源路径仍相对于构建上下文。 - WORKDIR 可以出现多次,从而更换shell的执行路径 5. RUN python3 -m pip install --upgrade pip 6. RUN pip3 install -r requirements.txt RUN命令的shell形式,更新pip同时安装依赖。 7. COPY . /app 复制命令 将当前目录的所有文件复制到/app目录下 8.CMD [ "python3", "main.py" ] CMD的作用是提供容器的默认指令,也就是我们docker run 的最后一个参数。CMD有三种形式,在一个Dockerfile中,如果有多个CMD指令,那么只有最后一个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) 如果CMD命令后只有参数,没有可执行的命令,那么它肯定是配合ENTRYPOINT使用的。同时要注意,如果是配合ENTRYPOINT的时候,CMD和ENTRYPOINT都要使用使用 JSON array 格式。如果用ENTRYPOINT进行改写,则如下所示。 ENTRYPOINT [ "python3" ] CMD [ "main.py" ]
打包镜像
1 2 3 docker build -t kuakua:latest . -t 设置镜像名称和标签,如果标签没有设定,默认是latest . 在当前目录寻找Dockerfile进行镜像打包。
运行容器
1 2 3 4 5 6 7 8 docker run -d -p 5001:5000 --name kuakua -v /Users/liqingwen/workplace/temp/kuakua/log:/log kuakua:latest # 详细解释 -d 表示以守护进程的形式进行执行,后台运行 -p 5001:5000 将容器的5000端口映射到宿主机的5001端口 --name kuakua 将当前容器命名为kuakua -v bind mount a volumn 将容器的log目录和本地的/Users/liqingwen/workplace/temp/kuakua/log做一个映射。如果容器端log目录下有内容更新,则本地的log目录也会同步更新。 kuakua:latest 镜像名称
项目地址
本项目完整代码已经在github开源,项目地址夸夸机器人 ,欢迎大家去尝试一下。
参考
dockerfile 官方参考文档
Dockerize your Flask Application