dockerfile

Posted yscl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了dockerfile相关的知识,希望对你有一定的参考价值。

一、概念

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执行指令生成(分层)镜像的流程:

  1. docker从基础镜像运行一个容器
  2. 执行一条指令并对容器作出修改
  3. 执行类似docker commit的操作提交一个新的镜像层
  4. docker再基于刚提交的镜像运行一个新容器
  5. 执行dockerfile中的下一条指令直到所有指令都执行完成

一般来说,我们可以将 Dockerfile 分为四个部分:

  • 基础镜像(父镜像)信息指令 FROM
  • 维护者信息指令 MAINTAINER
  • 镜像操作指令 RUNEVNADDWORKDIR
  • 容器启动指令 CMDENTRYPOINTUSER

二、基础命令

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被触发

三、小总结

从应用软件的角度来看,DockerfileDocker 镜像与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 对应镜像名称来进入环境看是否成功。

以上是关于dockerfile的主要内容,如果未能解决你的问题,请参考以下文章

构建 Dockerfile 使用非零代码 139 执行

dockerfile部署goweb项目

dockerfile部署goweb项目

dockerfile部署goweb项目

Dockerfile的理解

当使用CICD的Conducto时,我必须创建自己的dockerfile吗?