目录
- 制作容器镜像
- 使用Dockerfile制作镜像
- 准备所需文件
- 构建镜像
- 怎么不使用基础镜像来构建容器镜像
- 使用容器镜像
- 传递容器镜像
这篇文章讨论一下怎么使用docker制作容器镜像,容器镜像的使用,以及怎么传递容器镜像。
制作容器镜像
docker制作容器镜像推荐的方法就是使用Dockerfile,因为Dockerfile不仅可以方便的重复使用,而且还直观的记录了制作镜像的规则和过程,也方便查问题。
使用Dockerfile制作镜像
准备所需文件
看个简单的示例,比如有这么一个目录结构:
.
├── bin
│ └── main
├── Dockerfile
└── src
│ └── main.cpp
首先main就是用main.cpp生成的可执行程序。
然后看下Dockerfile文件内容:
FROM debian
COPY bin /demo/bin
WORKDIR /demo/bin
RUN chmod 777 ./main
RUN mkdir /demo/data
CMD ./main
解释一下Dockerfile文件中指令的含义:
- FROM debian:指定基础镜像,之后的指令都是基于这个基础镜像。
- COPY bin /demo/bin:将上下文目录中的bin目录复制到镜像的/demo/bin目录中。
- WORKDIR /demo/bin:指定工作目录,之后的指令的当前目录就是这个目录,容器启动时默认当前目录也是这个目录。
- RUN chmod 777 ./main:在构建镜像时(即docker build时)执行命令。
- RUN mkdir /demo/data:在构建镜像时(即docker build时)执行命令。
- CMD ./main:启动容器时(即docker run时)的默认命令,可以在docker run时使用参数覆盖。
其中
RUN chmod 777 ./main
RUN mkdir /demo/data
可以改成一条指令
RUN chmod 777 ./main
&& mkdir /demo/data
要不然镜像就会多一层。
构建镜像
文件准备好了,我们在这个目录中执行命令docker build -t demo:v1.0 -f ./Dockerfile .
就可以构建出包含前面编译出来的main程序的容器镜像,这个命令中的-t参数表示指定生成的镜像的名字和标签,-f参数表示指定要使用的Dockerfile,后面那个.表示上下文目录为当前目录,就是要打包的目录,Dockerfile中的一些指令比如COPY就会以这个目录为基础,注意上下文目录中尽量不要放镜像内不需要的文件,会影响效率。
构建完成之后使用docker images就可以查看到构建出来的镜像了。
怎么不使用基础镜像来构建容器镜像
前面介绍的Dockerfile中有一条FROM debian指令,是指明基础镜像,意思就是使用一个已经制作好的镜像作为基础镜像。那如果不想使用基础镜像,而是完全自定义,是不是不写这条指令就行了,不是的,因为FROM是Dockerfile的必备指令。
这里想说明一下,很多人说FROM必须是Dockerfile的第一条指令,其实不是,FROM是Dockerfile的必备指令,但FROM并不必须是第一条指令,比如第一条可以是ARG:
ARG base
FROM $base
既然必须指定基础镜像,那怎么不使用基础镜像来构建容器镜像呢,有办法的。虽然FROM指令是必须的,但是Docker中存在一个特殊的基础镜像叫scratch,这个镜像是空的,所以就可以FROM scratch,这个效果也就相当于不使用基础镜像来构建容器镜像了。
但是这样会比较难,首先容器镜像其实可以简单的理解为是一个rootfs文件系统,所以如果使用这种方法构建镜像,由于基础镜像是个空的,就需要我们自己制作一个rootfs文件系统,然后在Dockerfile中使用指令将自己制作的rootfs文件系统放进容器镜像,这种方式可以制作特别轻量级的容器镜像,但是会比较复杂,这篇文章里就不具体展开了。
使用容器镜像
容器镜像制作完成就可以使用了,那怎么使用呢,这个因为场景很多而且复杂,这篇文章不介绍那么多,这里就简单介绍一个比较常用的场景,那就是使用docker run
来使用容器镜像启动一个容器,比如使用命令docker run -it --rm --name demo demo:v1.0 /bin/bash
以交互的模式启动容器,然后在这个容器中执行所需操作。
传递容器镜像
容器的一大特点(也是特别受欢迎的一点)就是可以保证环境的一致性,这里就要涉及到容器镜像的传递了。
传递镜像主要使用两组命令完成。
方案一:
第一组命令是docker save和docker load,这组命令针对容器镜像,主要用在传递原始镜像的场景。
方案是使用docker save将镜像保存为归档文件,然后将归档文件传递到需要的机器上面,然后使用docker load从归档文件中导入镜像。
命令示例:
docker save -o demo.tar demo:v1.0:将镜像保存为归档文件,-o参数指定保存为的文件,这里就表示保存为当前目录下的demo.tar文件。
docker save -o demo.tar demo1:v1.0 demo2:v1.0 demo2:v2.0:将多个镜像保存为一个归档文件。
docker load -i ./demo.tar:从归档文件中导入镜像,归档文件就是使用docker save生成的文件,-i参数指定输入文件,即从哪个归档文件导入镜像。
方案二:
第二组命令是docker export和docker import,这组命令针对容器,主要用在需要传递容器执行过程中的一些状态的场景。
方案是使用docker export将容器保存为归档文件,然后将归档文件传递到需要的机器上面,然后使用docker import从归档文件中导入镜像。
命令示例:
docker export -o demo.tar CONTAINER:将容器保存为归档文件,CONTAINER可以使用容器id指定,-o参数指定保存为的文件,这里就表示保存为当前目录下的demo.tar文件。
docker import demo.tar demo:v1:使用归档文件创建镜像,归档文件是使用docker export生成的。
区别:
使用docker save和docker load保存的数据会比较完整,会包括镜像历史,使用docker export和docker import不会保存镜像历史,因为是从容器导出为的容器镜像。