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查看)。

相关推荐
小安运维日记1 分钟前
Linux云计算 |【第三阶段】PROJECT1-DAY1
linux·运维·云计算·apache
小的~~18 分钟前
k8s使用本地docker私服启动自制的flink集群
docker·flink·kubernetes
pyliumy18 分钟前
rsync 全网备份
linux·运维·服务器
苹果醋340 分钟前
SpringCloud系列之一---搭建高可用的Eureka注册中心
运维·nginx
诚诚k1 小时前
docker存储
运维·docker·容器
sorel_ferris1 小时前
Ubuntu-24.04中Docker-Desktop无法启动
linux·ubuntu·docker
ggb19991 小时前
【python的坑】vpn下,python request报错 check_hostname requires server_hostname
linux·运维·服务器
数据智能老司机1 小时前
Kubernetes从入门到精通系列——外部 DNS 和全局负载均衡
云原生·容器·kubernetes
小O_好好学1 小时前
vi | vim基本使用
linux·编辑器·vim
-SGlow-1 小时前
Linux相关概念和重要知识点(4)(自举、vim)
linux·运维·vim