06 - 镜像管理

1 了解镜像

Docker镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。

但注意, 镜像不包含任何动态数据( /proc、/sys,其中,/proc里面装的主要是内核参数,在内核运行状态不同时里面的值是不一样的,而/sys目录则包含了系统资源的管理信息,这两个目录中的数据都是动态生成的) ,因此,其内容在构建好之后一般是不会变的。这里,第一,你要知道什么是动态数据,第二,将来我们要自己装一个linux操作系统,你想把这个linux做成一个容器镜像,其实很简单,就是把linux里面所有的文件目录打包一份就行了,但是打包的时候会把/proc和/sys这两个目录排除。(因此, 容器镜像不包含内核,容器共用宿主机的内核)

2 镜像的制作

2.1 通过对系统打包的方式制作镜像

1)最小化安装一个操作系统

2)将此系统文件打包,把装的一个系统做成一个容器镜像,也就是把根文件系统打个包就行了(除了/proc和/sys之外)

bash 复制代码
[root@node02 ~]# tar -cvf --numeric-owner --exclude=/proc --exclude=/sys /data/centos7u2.tar /

3)将打包文件拷贝到运行容器的主机上

bash 复制代码
[root@node02 ~]# scp  centos7u2.tar  192.168.1.72:/root

4)利用打包文件生成镜像

bash 复制代码
[root@node02 ~]# docker  import  centos7u2.tar  docker.io/centos7u2:latest
[root@node02 ~]# docker images
REPOSITORY                       TAG                 IMAGE ID            CREATED             SIZE
docker.io/centos7u2              latest              1e1148e4cc2c        30 seconds ago      987 MB

5)使用自己生成的镜像创建容器做测试

bash 复制代码
[root@node02 ~]# docker run -itd --name c1 docker.io/centos7u2 /bin/bash

2.2 基于Dockerfile文件制作镜像

1)编写dockerfile文件

bash 复制代码
[root@node02 ~]# cat /root/test01 
	FROM local-test/centos7.2:v1				
	RUN yum install -y httpd &&  yum install -y vsftpd 

	解释:
		FROM:用于指定一个基础镜像
		RUN:执行任务,建议同一个任务的多条指令使用&&连接多个命令完成 

2)构建镜像

bash 复制代码
[root@node02 ~]# docker build -t centos7.2-httpd:v2 -f test01 /root

	参数说明:	
	    -t:用于指定镜像名称、标记
	    -f:指定dockerfile名称 

3)查看镜像

bash 复制代码
[root@node02 ~]# docker images 
REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
centos7.2-httpd        v2                  2cdfd7a685f6        2 minutes ago       1.08 GB

3 Dockerfile指令说明

3.1 FROM

FROM < image >

用于指定基础镜像

3.2 MAINTAINER

MAINTAINER < name >

用于指定镜像的作者信息,当执行docker inspect指令时会有输出 。

3.3 RUN

RUN < command >

或者

RUN ["command","arg1","arg2"]

用于执行基础镜像支持的任何指令;

例如:

RUN yum install -y net-tools

RUN ["yum","install","-y","net-tools"]

3.4 CMD && ENTRYPOINT

3.4.1 CMD

CMD < command > < arg1 > < arg2 >

或者

CMD ["command","arg1","arg2"]

用于指定容器启动时执行的操作;

注意:一个dockerfile中只能有一条 CMD 指令,如果有多条则仅执行最后一条;

bash 复制代码
# 使用CMD指令
FROM ubuntu
CMD ["echo", "Hello World"]

3.4.2 ENTRYPOINT

ENTRYPOINT 和 CMD 指令的用法很相似:

ENTRYPOINT < command > < arg1 > < arg2 >

或者

ENTRYPOINT ["command","arg1","arg2"]

用于指定容器启动时执行的操作;

注意:一个dockerfile中只能有一条 ENTRYPOINT指令,如果有多条则仅执行最后一条;

bash 复制代码
# 使用ENTRYPOINT指令
FROM ubuntu
ENTRYPOINT ["echo", "Hello World"]

另外,ENTRYPOINT指令还可以与CMD指令配合使用,此时,CMD指令后跟的不再是完整的可执行命令,而仅是作为ENTRYPOINT指令后的参数使用,如下所示:

bash 复制代码
# ENTRYPOINT 和 CMD 指令配合使用
FROM ubuntu
ENTRYPOINT ["cat"]
CMD ["-n","/etc/passwd"]

3.4.3 CMD 和 ENTRYPOINT 的区别

区别:

如果在运行docker run命令时指定了参数,那么,将会覆盖CMD中指定的参数,而ENTRYPOINT指令不会被覆盖,而是被附加到docker run命令的参数之前。

总结来说:CMD用于定义默认的容器启动命令,可以被覆盖,而ENTRYPOINT用于定义容器启动的主要命令,不会被覆盖。

案例:

使用 Dockerfile 构建 centos 镜像,在 Dockerfile 中使用 CMD 和 ENTRYPOINT 。当 docker run + 参数 的时候进行 CMD 和 ENTRYPOINT 的测试,CMD指定的参数是否会被覆盖,以及 ENTRYPOINT 指定的参数是否会附加到docker run命令的参数之前。

【测试CMD】

1)编写dockerfile文件

$ vim dockerfile-centos-test

FROM centos

CMD ["ls","-a"]

2)构建镜像

$ docker build -f dockerfile-centos-test -t cmd-test:0.1 .

3)运行镜像

$ docker run cmd-test:0.1

可以看到,列出了所有目录。

4)这个时候我们在docker run 的时候追加一个命令参数 -l

$ docker run cmd-test:0.1 -l

可以看到,出现了错误,在CMD的情况下,加 -l 替换了dockerfile中的 CMD ["ls","-l"],但是由于 -l 不是命令,所以就报错了。

5)我们将 docker run 的命令参数 -l 改为 ls

$ docker run cmd-test:0.1 ls

可以看到,这个时候就执行成功了。

【测试 ENTRYPOINT】

1)编写dockerfile文件

$ vim dockerfile-centos-test

FROM centos

ENTRYPOINT ["ls","-a"]

2)构建镜像

$ docker build -f dockerfile-centos-test -t cmd-test:0.1 .

3)运行镜像

$ docker run cmd-test:0.1

4)这个时候追加一个命令 -l (使之成为 ls -al )

$ docker run cmd-test:0.1 -l

总结一下:CMD的情况下,docker run的参数 -l 替换了CMD的 ls -a。而ENTRYPOINT的情况下,-l 参数追加到了 ls -a 的后面,使之变成了ls -al。

3.5 ARG

ARG < key >=< value >

Docker 1.9 版本 后新加入的指令,ARG定义的变量只有在构建image时有效,建立完成后变量消失;

3.6 USER

USER < name >

用于设置启动容器的用户,默认为root

3.7 EXPOSE

EXPOSE < port1 > < port2 > ...

用于设置容器启动时,要映射到物理机的端口;容器启动后,会将该端口映射到物理机上的随机端口;

3.8 ENV

ENV < key > < value >

用于为容器设置环境变量,可以使用docker inspect查看;也可以通过docker run --env < key >=< value >设置或修改环境变量;(该变量设置后,后续的RUN指令都可以使用该变量)

3.9 ADD && COPY

3.9.1 ADD

ADD < src > < dest >

用于将src指定的文件复制到容器的目录

例如:
ADD /tmp/nginx-1.13.4.tar.gz /tmp/

1)所有拷贝到容器中的文件及目录权限为0755,uid及gid均为0;

2)src如果是一个目录,那会将该目录下所有文件拷贝到容器中,不包括目录;

3)如果src是文件且dest不以/结束,dest会被识别为文件,src中的内容会把dest文件内容覆盖;

4)如果src是文件且dest以/结束,则会将src文件拷贝到dest目录;;

如果源文件是一个tar压缩包的话,压缩格式为gzip,bzip2以及xz的情况下,ADD指令将会自动解压缩这个压缩文件到目标路径中,在某些情况下这个自动解压缩的功能非常有用。

3.9.2 COPY

COPY < src > < dest >

用于复制本地主机的src文件(为Dockerfile所在目录的相对路径、文件或者目录)到容器的dest(dest路径不存在时,会自动创建)。

此外,还需要注意一点,使用 COPY 指令,源文件的各种元数据都会保留,比如读、写、执行权限、文件变更时间等。(这个特性对于镜像定制很有用,特别是构建相关文件都在使用 Git 进行管理的时候)

3.9.3 ADD 和 COPY 的区别

共同点:

都可以将主机上的资源加入到Dockerfile制作的镜像中。

不同点:

官方建议:

1)尽可能的使用 COPY,因为 COPY 的语义很明确,就是复制文件而已;

2)需要自动解压缩的场合,再使用ADD;

另外,需要注意的是,ADD 指令会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。因此在 COPY 和 ADD 指令中选择的时候,可以遵循这样的原则:所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合使用 ADD。

3.10 WORKDIR

WORKDIR < path >

用于切换目录,类似于cd命令;(对RUN, CMD, ENTRYPOINT指令生效)

3.11 VOLUME

VOLUME ["mount_point"]

用于创建一个本机或者为其他容器使用的挂载点,用于数据的持久化保存 。

例如:
FROM base VOLUME ["/tmp/data"]

通过dockerfile的 VOLUME 指令可以在镜像中创建挂载点,这样只要通过该镜像创建的容器都有了挂载点,但值得注意的是通过VOLUME 指令创建的挂载点,无法指定主机上对应的目录,而是自动生成的(可以通过docker inspect查看)。

相关推荐
无敌小茶18 分钟前
Linux学习笔记之环境变量
linux·笔记
Harbor Lau31 分钟前
Linux常用中间件命令大全
linux·运维·中间件
漫谈网络1 小时前
基于 Netmiko 的网络设备自动化操作
运维·自动化·netdevops·netmiko
꧁坚持很酷꧂1 小时前
Linux Ubuntu18.04下安装Qt Craeator 5.12.9(图文详解)
linux·运维·qt
时迁2471 小时前
【k8s】k8s是怎么实现自动扩缩的
云原生·容器·kubernetes·k8s
凉、介2 小时前
PCI 总线学习笔记(五)
android·linux·笔记·学习·pcie·pci
电鱼智能的电小鱼2 小时前
EFISH-SBC-RK3588无人机地面基准站项目
linux·网络·嵌入式硬件·机器人·无人机·边缘计算
电鱼智能的电小鱼2 小时前
基于 EFISH-SBC-RK3588 的无人机环境感知与数据采集方案
linux·网络·嵌入式硬件·数码相机·无人机·边缘计算
小诸葛的博客3 小时前
详解Linux中的定时任务管理工具crond
linux·运维·chrome
一默19913 小时前
CentOS 7.9升级OpenSSH到9.9p2
linux·运维·centos