基于Dockerfile创建镜像

193 阅读8分钟

前言

  • Dockerfile是一个文本格式的配置文件,用户可以使用Dockerfile快速创建自定义的镜像。

一、Docker镜像的创建

创建镜像有三种方法:

  1. 基于已有镜像创建
  2. 基于本地模板创建
  3. 基于Dockerfile创建(重点)

1.基于现有镜像创建

(1) 首先启动一个镜像,在容器里做修改

docker create -it centos:7 bash

docker ps -a
CONTAINER ID   IMAGE      COMMAND   CREATED          STATUS    PORTS     NAMES
fb555aed6d9c   centos:7   "bash"    17 seconds ago   Created             agitated_germain

docker start fb555aed6d9c
yum install net-tools -y			
exit

[root@localhost ~]# docker create -it centos:7 bash
a0e0b9ee23f6c61f62a33bd909b65adbb0414cec3d73c6e96729eb3e1e4dd49e
[root@localhost ~]# docker ps -a
CONTAINER ID   IMAGE      COMMAND       CREATED         STATUS                   PORTS     NAMES
a0e0b9ee23f6   centos:7   "bash"        6 seconds ago   Created                            modest_jepsen
#启动容器
[root@localhost ~]# docker start modest_jepsen
# 可以在容器里面安装net-tools工具
[root@localhost ~]# docker exec -it modest_jepsen bash
[root@a0e0b9ee23f6 /]# yum install -y net-tools

```js

(2) 然后将修改后的容器提交为新的镜像,需要使用该容器的ID号创建新镜像

[root@localhost ~]# docker commit -m "new net-tools" -a "stevelu" a0e0b9ee23f6 centos:test1
sha256:40319e6b8822918affaacb40392d9eb30b8603b56d66c030c1a3ee9da5711d36
[root@localhost ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
centos       test1     40319e6b8822   40 seconds ago   375MB
centos       7         eeb6ee3f44bd   9 months ago     204MB

```js

image.png

2.基于本地模板创建

通过导入操作系统模板文件可以生成镜像,模板可以从OPENVZ开源项目下载,下载地址为: wiki.openvz.org/Download/te…

wget http://download.openvz.org/template/precreated/debian-7.0-x86-minimal.tar.gz
可在主机上复制下载地址下载debian镜像导入,虚拟机上下载较慢

```js
#导入debian压缩包
[root@localhost ~]# ls
anaconda-ks.cfg  debian-7.0-x86-minimal.tar.gz  initial-setup-ks.cfg  original-ks.cfg  
#生成镜像
[root@localhost ~]# docker import debian-7.0-x86-minimal.tar.gz -- debian:v1
sha256:0cc18c818a1948becb66cab4b4c880f815200e67fffcbb9bd48f67822010247b
#或
cat debian-7.0-x86-minimal.tar.gz | docker import - debian:v1

#查看镜像
[root@localhost ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
debian       v1        0cc18c818a19   16 seconds ago   215MB
#启动容器
[root@localhost ~]# docker run -itd debian:v1 bash
c1ed22a0152567a12b3f0a8b3fa57f407ca1fe55d631ece1bb9860b7fa4efb3a
[root@localhost ~]# docker ps -a
CONTAINER ID   IMAGE       COMMAND       CREATED          STATUS                   PORTS     NAMES
c1ed22a01525   debian:v1   "bash"        5 seconds ago    Up 5 seconds                       peaceful_goldwasser

```js

image.png

3.基于Dockerfile创建

联合文件系统(UnionFS)

image.png

镜像加载原理

image.png

为什么Docker里的centos的大小才200M?

image.png

Dockerfile

1.Docker镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数 (如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。

2.镜像的定制实际上就是定制每一层所添加的配置文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么镜像构建透明性的问题、体积的问题就都会解决。这个脚本就是Dockerfile。 image.png

Docker镜像结构的分层

镜像不是一个单一的文件,而是有多层构成。容器其实是在镜像的最上面加了一层读写层,在运行容器里做的任何文件改动,都会写到这个读写层。如果删除了容器,也就删除了其最上面的读写层,文件改动也就丢失了。Docker使用存储驱动管理镜像每层内容及可读写层的容器层。

image.png (1) Dockerfile 中的每个指令都会创建一个新的镜像层;

(2)镜像层将被缓存和复用;

(3)当Dockerfile的指令修改了,复制的文件变化了,或者构建镜像时指定的变量不同了,对应的镜像层缓存就会失效;

(4) 某一层的镜像缓存失效,它之后的镜像层缓存都会失效;

(5) 镜像层是不可变的,如果在某一层中添加一个文件,然后在下一层中删除它,则镜像中依然会包含该文件,只是这个文件在Docker容器中不可见了。

image.png

  1. bootfs:bootfs加载器+内核,容器都是共享内核的,所以都有相同的bootfs
  2. rootfs只读层:rootfs可以有多层,对外表现看起来就是一个整体
  3. 使用镜像运行一个容器实例时,就会在rootfs只读层上挂载一层可读可写层

Dockerfile操作常用命令

1 FORM 镜像 指定新镜像所基于的镜像,第一条指令必须为FROM指令,每创建一个镜像就需要一条FROM指令

2 MAINTAINER 名字 说明新镜像的维护人信息

3 RUN 命令 在所基于的镜像上执行命令,并提交到新的镜像中当命令较长时,可以使用\来换行

4 ENTRYPOINT ENTRYPOINT [“要运行的程序”,“参数1”,“参数2”]

image.png

CMD

两种格式:

1.exec形式:CMD [“要运行的程序”,“参数1”, “参数2”]

2.shell形式: CMD 命令 参数1 参数2 启动容器时默认执行的命令或者脚本,Dockerfile只能有–条CMD命令。如果指定多条命令,只执行最后一条命令。

如果在dockerrun时指定了命令或者镜像中有ENTRYPOINT,那么cmd就会被覆盖。

CMD可以为ENTRYPOINT 指令提供默认参数 image.png

EXPOSE 端口号

指定新镜像加载到Docker时要开启的端口

ENV 环境变量变量值

设置一个环境变量的值,会被后面的RUN使用

 ADD 源文件/目录 目标文件/目录

将源文件复制到镜像中,源文件要与Dockerfile 位于相同目录中,或者是一个URL

COPY

COPY 源文件/目录目标文件/目录

只复制本地主机_上的文件/目录复制到目标地点,源文件/目录要与Dockerfile在相同的目录中

VOLUME [“目 录"]

在容器中创建–个挂载点

 USER 用户名/UID

指定运行容器时的用户

WORKDIR 路径

为后续的RUN、CMD、 ENTRYPOINT 指定工作目录

ONBUILD 命令

指定所生成的镜像作为一个基础镜像时所要运行的命令。

当在一个Dockerfile 文件中加上ONBUILD指令, 该指令对利用该Dockerfile构建镜像 (比如为A镜像) 不会产生实质性影响。

但是当编写一个新的Dockerfile文件来基于A镜像构建一个镜像 ( 比如为B镜像)时,这时构造A镜像的Dockerfile文件中的ONBUILD指令就生效了,在构建B镜像的过程中,首先会执行ONBUILD指令指定的指令,然后才会执行其它指令。

AGR

设置编译镜像时加入的参数

使用ENV指令定义的环境变量始终会覆盖同名的ARG指令

ARG  CONT_IMG_VER
ENV  CONT_IMG_VER=V1.0.0
RUN  echo $CONT_IMG_VER
docker build --build-arg VER=v2.0

```js

创建镜像 编写完成Dockerfile之后,可以通过docker build命令来创建镜像。

基本的格式为docker build [选项] 路径,该命令将读取指定路径下(包括子目录)的Dockerfile,并将该路径下所有内容发送给Docker服务端,由服务端来创建镜像。因此一般建议放置Dockerfile的目录为空目录。

另外,可以通过.dockerignore文件(每一行添加一条匹配模式)来让Docker忽略路径下的目录和文件。 要指定镜像的标签信息,可以通过-t选项。

image.png

dockerfile案例

构建Apache镜像

[root@localhost ~]# cd /opt/
#创建工作目录
[root@localhost opt]# mkdir apache
[root@localhost opt]# cd apache/
#准备网站文件
[root@localhost apache]# echo "i am stevelu" > index.html
#编写Dockerfile文件
[root@localhost apache]# vim Dockerfile
    #指定基础镜像
    FROM centos:7
    #指定维护信息
    MAINTAINER this is apache image <stevelu 2022-6-27>

    #指定构建镜像的操作,安装Apache,暴露端口
    RUN yum -y update && yum install -y httpd
    EXPOSE 80

    #复制网站文件到镜像中
    ADD index.html /var/www/html/

    #指定容器启动时运行的命令
    ENTRYPOINT ["/usr/sbin/apachectl","-D","FOREGROUND"]

#构建镜像  -t指定镜像名称  . 指定当前目录
[root@localhost apache]# docker build -t httpd:v1 .

```js

因为VIM真是难用,我就在自己电脑上用VS code编写好再复制进去,VS code里面也有dockerfile的插件,很好用 image.png image.png

如果有报错,应该是没有开启ip转发功能

修改vim /usr/lib/sysctl.d/00-system.conf

加入net.ipv4.ip_forward=1

重启网卡,重启docker服务,删掉失败的镜像或容器重新操作

#运行容器,并指定端口映射
[root@localhost apache]# docker run -d -p 1314:80 httpd:v1
bf75790c8a1f3c680035413d77a29aef87de5f82249dc4f95f01b8f5212431d0
[root@localhost apache]# docker ps -a
CONTAINER ID   IMAGE      COMMAND                  CREATED         STATUS         PORTS                                   NAMES
bf75790c8a1f   httpd:v1   "/usr/sbin/apachectl…"   9 seconds ago   Up 8 seconds   0.0.0.0:1314->80/tcp, :::1314->80/tcp   keen_euclid

```js

image.png

总结

注意:dockerfile构建镜像前要创建一个工作目录,docker build会扫描当前目录下所有文件

64b6ae16553d7fd2bfcda30afbe081b.png