一、概念
Dockerfile
是自动构建 docker
镜像的构建文件,是由一系列命令和参数构成的脚本。 用户可以使用 Dockerfile
快速创建自定义的镜像。Dockerfile
中的命令非常类似于 linux
下的 shell
命令。
上图就清晰的表明了 Dockerfile
镜像、容器和 Dockerfile
三者之间的关系。
那么dockerfile
文件具体的内容是什么样的呢? 最简单的方式就是参考官方镜像的dockerfile
文件, 以centos7
为例。
FROM scratch # 基础镜像
ADD centos-7-x86_64-docker.tar.xz /
LABEL org.label-schema.schema-version="1.0"
org.label-schema.name="CentOS Base Image"
org.label-schema.vendor="CentOS"
org.label-schema.license="GPLv2"
org.label-schema.build-date="20191001"
CMD ["/bin/bash"]
Dockerfile
是由一行行命令语句组成,并且支持已 #
开头的注释行。每条保留字指令都必须为大写字母且后面要跟随至少一个参数 , 并且指令按照从上到下,顺序执行 ,每条指令都会创建一个新的镜像层,并对镜像进行提交 。
简单分析一下dockerfile
执行指令生成(分层)镜像的流程:
docker
从基础镜像运行一个容器- 执行一条指令并对容器作出修改
- 执行类似
docker commit
的操作提交一个新的镜像层 - docker再基于刚提交的镜像运行一个新容器
- 执行
dockerfile
中的下一条指令直到所有指令都执行完成
一般来说,我们可以将 Dockerfile
分为四个部分:
- 基础镜像(父镜像)信息指令
FROM
- 维护者信息指令
MAINTAINER
- 镜像操作指令
RUN
、EVN
、ADD
和WORKDIR
等 - 容器启动指令
CMD
、ENTRYPOINT
和USER
等
二、基础命令
FROM
基础镜像,当前新镜像是基于哪个镜像的
MAINTAINER
镜像维护者的姓名和邮箱地址
RUN
容器构建时需要运行的命令
EXPOSE
当前容器对外暴露出的端口
WORKDIR
指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点
ENV
用来在构建镜像过程中设置环境变量 。
ENV MY_PATH /usr/mytest
这个环境变量可以在后续的任何RUN指令中使用,这就如同在命令前面指定了环境变量前缀一样;
也可以在其它指令中直接使用这些环境变量,
比如:WORKDIR $MY_PATH
ADD
将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包
COPY
将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置
VOLUME
容器数据卷,用于数据保存和持久化工作
CMD
CMD
命令用于启动容器时默认执行的命令,CMD
命令可以包含可执行文件,也可以不包含可执行文件。不包含可执行文件的情况下就要用 ENTRYPOINT
指定一个,然后 CMD
命令的参数就会作为ENTRYPOINT
的参数。
Dockerfile
中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换 。
CMD
命令有三种格式:
CMD ["executable","param1","param2"]
:推荐使用的exec
形式。CMD ["param1","param2"]
:无可执行程序形式CMD command param1 param2
:shell 形式。
ENTRYPOINT
指定一个容器启动时要运行的命令。
ENTRYPOINT
的目的和CMD
一样,都是在指定容器启动程序及参数 。
CMD
命令会被 Docker
命令行传入的参数覆盖:docker run busybox /bin/echo Hello
Docker
会把 CMD
里的命令覆盖。 而ENTRYPOINT
则不会。
ONBUILD
当构建一个被继承的Dockerfile
时运行命令,父镜像在被子继承后父镜像的onbuild
被触发
三、小总结
从应用软件的角度来看,Dockerfile
、Docker
镜像与Docker
容器分别代表软件的三个不同阶段,
-
Dockerfile
是软件的原材料 -
Docker
镜像是软件的交付品 -
Docker
容器则可以认为是软件的运行态。
Dockerfile
面向开发,Docker
镜像成为交付标准,Docker
容器则涉及部署与运维,三者缺一不可,合力充当Docker
体系的基石。
Dockerfile
需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等。
Docker镜像
在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行 Docker镜像时,会真正开始提供服务。
Docker容器
容器是直接提供服务的。
四、生成包含python3环境的centos7系统
commit方式
# 拉取centos:7的镜像
docker pull centos:7
# 查看镜像是否存在
docker images
# 创建并进入centos7容器环境
docker run -it --name='django-python3' centos:7 /bin/bash
# 安装相关依赖
yum install -y openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel
gcc automake autoconf libtool make wget
# 下载python安装包, 如果速度太慢可以选择先在本机下好, 再利用docker cp命令复制到里面, 我就是先下好的再copy过去
wget https://www.python.org/ftp/python/3.6.7/Python-3.6.7.tar.xz
# 解压
tar -xf Python-3.6.7.tar.xz
# 进入目标文件
cd Python-3.6.7
# 配置安装路径:/usr/local/python3
./configure --prefix=/usr/local/python3
# 编译并安装
make && sudo make install
# 建立软连接:终端命令 python3,pip3
ln -s /usr/local/python3/bin/python3.6 /usr/bin/python3
ln -s /usr/local/python3/bin/pip3.6 /usr/bin/pip3
# 删除安装包与文件
rm -rf Python-3.6.7
rm -rf Python-3.6.7.tar.xz
# 更新pip版本
pip3 install --upgrade pip3
# 查看当前运行的容器id
docker ps
docker commit -a yscl -m 'django-python3' 3e57 yscl/django-python3
# 这样就创建出了一个基于centos7的含python3的镜像了。
dockerfile
方式
编写方式可以参考模仿docker-hub上python官方镜像的写法。
中间的run的命令其实就是把上面一步步命令的写成了一行, 然后一起执行。
# 依赖centos:7制作出来的镜像
FROM centos:7
# 指定作者信息
MAINTAINER yscl<xxx.com>
# 添加python安装包文件到镜像, add命令会自动copy并解压
ADD Python-3.6.7.tar.xz /root/
# 安装
RUN set -ex
# 预安装所需组件
&& yum install openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel
gcc automake autoconf libtool make wget
&& cd /root/Python-3.6.7
&& ./configure prefix=/usr/local/python3
&& make
&& make install
&& make clean
&& rm -rf /root/Python-3.6.7*
&& yum install -y epel-release
&& yum install -y python-pip
# 设置python3的软连接
RUN set -ex
# 配置默认为python3
&& ln -s /usr/local/python3/bin/python3.6 /usr/bin/python3
&& ln -s /usr/local/python3/bin/pip3 /usr/bin/pip3
# 基础环境配置
RUN set -ex
# 修改系统时区为东八区
&& rm -rf /etc/localtime
&& ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
&& yum install -y vim
# 安装定时任务组件
&& yum -y install cronie
# 支持中文
RUN yum install kde-l10n-Chinese -y
RUN localedef -c -f UTF-8 -i zh_CN zh_CN.utf8
# 更新pip版本
RUN pip3 install --upgrade pip3
ENV LC_ALL zh_CN.UTF-8
# 默认的启动时python3的交互环境
CMD ["python3"]
构建镜像
docker build -t centos7-python3.6 . (最后这个点是从当前目录寻找Dockerfile
文件,-t 是镜像名称, 当然也可以通过-f参数指定相应的路径), 我这里已经到了dockerfile
的路径了, 并且还要把python3.6的安装包事先下载好, 放到这。
构建完, 可以通过docker images
命令和docker run -it
对应镜像名称来进入环境看是否成功。