文章目录
- docker镜像管理
-
- 镜像分层结构
- 镜像构建
-
- [docker commit](#docker commit)
- Dockerfile
- 封装nginx
- 镜像优化
docker镜像管理
镜像分层结构

如图是nginx的分层

镜像构建
docker commit
bash
[root@server1 ~]# docker run -it --name demo busybox
/ # touch file1 file2 file3
/ # ls
bin etc file2 home lib64 root tmp var
dev file1 file3 lib proc sys usr
ctrl+d: 退出容器后容器自动关闭
ctrl+pq: 退出容器后继续在后台运行
#显示所有容器
[root@server1 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7b46fa695add busybox "sh" 38 seconds ago Exited (0) 13 seconds ago demo
#提交容器变更到新的镜像
[root@server1 ~]# docker commit -m "add files" demo demo:v1
sha256:0c62baa3e9ad7ea0baabf26e80d915118f8612cb14644616ed0d0e0c94772571
#查看新镜像,有两层
[root@server1 ~]# docker history demo:v1
IMAGE CREATED CREATED BY SIZE COMMENT
0c62baa3e9ad 17 seconds ago sh 27B add files
c6348fa86ba0 3 months ago BusyBox 1.38.0 (glibc), Debian 13 4.45MB
这种方式看不到具体做了什么,不利于安全审计
Dockerfile
镜像层(Image Layer)是构成 Docker 镜像的基本单位。每个镜像都是由一系列只读的层叠加而成的。这些层中的每一层都代表了文件系统的一个增量变更。当创建一个新的镜像时,Docker 会基于基础镜像添加新的层,每一层包含了对文件系统的修改,如添加、删除或修改文件。
镜像层特点:
-
只读性:每个镜像层都是只读的,这意味着一旦创建了一个层,就不能再对其进行修改。这种设计保证了镜像的一致性和不可变性。
-
增量更新:每个层只包含相对于前一层的差异部分。例如,如果一个层只是向文件系统中添加了一个新文件,那么这个层就只包含那个文件的信息,而不包含整个文件系统的完整副本。 • 共享性:多个镜像可以共享相同的底层。例如,如果你有两个不同的镜像,它们都是基于同一个基础镜像构建的,那么这两个镜像可以共享基础镜像的所有层,从而节省磁盘空间。
-
联合挂载:Docker 使用一种称为联合文件系统(Union File System, UnionFS)的技术来将这些只读层合并成一个统一的文件系统视图。它们可以被组合在一起以形成一个完整的镜像。当对镜像进行修改时,实际上是在创建一个新的层,这个新层包含了所做的修改,而底层的层则保持不变。这种分层的设计使得容器镜像非常灵活和高效,因为它可以充分利用共享层来减少存储空间的占用,并且可以快速构建和分发新的镜像。

镜像层的工作原理:
-
构建过程:当你使用
docker build命令从Dockerfile构建镜像时,Docker会逐条解析Dockerfile中的指令,并为每条指令创建一个新的层。例如,RUN,COPY,ADD等命令都会生成新的层。 -
缓存机制:
Docker在构建过程中会利用缓存来加速构建。如果Dockerfile中的某条指令之前已经执行过并且没有发生变化,Docker就可以直接使用之前的缓存层,而不需要重新执行该指令。 -
容器运行:当启动一个容器时,
Docker会在所有只读层之上添加一个可写层(通常称为" 容器层 ")。任何对文件系统的修改都会写入这个可写层,而不是修改底层的只读层。这样即使容器停止或被删除,只读层仍然保持不变。 -
存储优化:由于多个镜像和容器可以共享相同的底层,
Docker可以高效地管理磁盘空间。此外,只有实际发生变更的部分才会占用额外的空间,减少了存储需求。
常用参数:
- FROM
bash
指定base镜像,如果本地不存在会从远程仓库下载。
- COPY 、ADD
bash
把文件从build context复制到镜像
src必须指定build context中的文件或目录
- ENV
bash
设置环境变量,变量可以被后续的指令使用
ENV HOSTNAME sevrer1.example.com
- EXPOSE
bash
如果容器中运行应用服务,可以把服务端口暴露出去:
EXPOSE 80
- VOLUME
bash
申明数据卷,通常指定的是应用的数据挂在点:
VOLUME ["/var/www/html"]
- WORKDIR
bash
为RUN、CMD、ENTRYPOINT、ADD和COPY指令设置镜像中的当前工作目录,如果目录不存在会自动创建。
- RUN
bash
在容器中运行命令并创建新的镜像层,常用于安装软件包
RUN yum install -y vim
- CMD 与 ENTRYPOINT
bash
这两个指令都是用于设置容器启动后执行的命令,但CMD会被docker run后面的命令行覆盖,而ENTRYPOINT不会被忽略,一定会被执行。
docker run后面的参数可以传递给ENTRYPOINT指令当作参数。
Dockerfile中只能指定一个ENTRYPOINT,如果指定了很多,只有最后一个有效。
- Shell和exec格式的区别
bash
# cat Dockerfile
FROM busybox
ENV name world
ENTRYPOINT echo "hello, $name"

- Shell格式底层会调用/bin/sh -c来执行命令,可以解析变量,而下面的exec格式不会:
bash
# cat Dockerfile
FROM busybox
ENV name world
ENTRYPOINT ["/bin/echo", "hello, $name"] #这个不会出现解析
- 需要改写成以下形式:
bash
# cat Dockerfile
FROM busybox
ENV name world
ENTRYPOINT ["/bin/sh", "-c", "echo hello, $name"] #这样写才对
- Exec格式时,ENTRYPOINT可以通过CMD提供额外参数,CMD的额外参数可以在容器启动时动态替换。在shell格式时ENTRYPOINT会忽略任何CMD或docker run提供的参数。
bash
# cat Dockerfile
FROM busybox
ENTRYPOINT ["/bin/echo", "hello"]
CMD ["world"]

示例
bash
[root@server1 ~]# mkdir docker
[root@server1 ~]# cd docker/
[root@server1 docker]# vim Dockerfile
FROM busybox
RUN touch file1 file2 file3
COPY os.sql /
[root@server1 docker]# cp /root/os.sql .
[root@server1 docker]# ls
Dockerfile os.sql
[root@server1 docker]# docker build -t demo:v2 .
[root@server1 docker]# docker images demo:v2
[root@server1 docker]# docker history demo:v2

清理测试用例
bash
[root@server1 docker]# ls
Dockerfile os.sql
[root@server1 docker]# rm -f *
[root@server1 docker]# ls
[root@server1 docker]# docker images demo
REPOSITORY TAG IMAGE ID CREATED SIZE
demo v2 fe1649903f38 13 minutes ago 6.03MB
demo v1 0c62baa3e9ad 3 hours ago 4.45MB
demo v4 ae7fe0f39606 3 months ago 4.45MB
demo v3 22edc42c18c0 3 months ago 4.45MB
[root@server1 docker]# docker rmi fe1649903f38 0c62baa3e9ad ae7fe0f39606 22edc42c18c0
[root@server1 docker]# docker images demo
REPOSITORY TAG IMAGE ID CREATED SIZE
封装nginx
官网下载安装包:nginx: download,并拖入目录
bash
[root@server1 docker]# docker pull docker.1ms.run/centos:7
[root@server1 docker]# docker images centos
REPOSITORY TAG IMAGE ID CREATED SIZE
centos 7 eeb6ee3f44bd 4 years ago 204MB
#复制yum源
[root@server1 docker]# cd /etc/yum.repos.d/
[root@server1 yum.repos.d]# ls
CentOS-Base.repo docker-ce.repo
[root@server1 yum.repos.d]# cp CentOS-Base.repo ~/docker/
#编辑dockerfile文件
[root@server1 yum.repos.d]# cd /root/docker/
[root@server1 docker]# vim Dockerfile
FROM centos:7
RUN rm -f /etc/yum.repos.d/*.repo
COPY CentOS-Base.repo /etc/yum.repos.d/
RUN yum install -y gcc make pcre-devel openssl-devel
ADD nginx-1.30.4.tar.gz /mnt/
WORKDIR /mnt/nginx-1.30.4
RUN sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc
RUN ./configure --with-http_ssl_module --with-http_stub_status_module
RUN make
RUN make install
EXPOSE 80
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
#确保资源文件都在当前目录
[root@server1 docker]# ls
CentOS-Base.repo Dockerfile nginx-1.30.4.tar.gz
#构建镜像
[root@server1 docker]# docker build -t webserver:v1 .
[root@server1 docker]# docker images webserver
REPOSITORY TAG IMAGE ID CREATED SIZE
webserver v1 e983577bf2ce About a minute ago 553MB
#启动容器
[root@server1 docker]# docker run -d --name web1 webserver:v1
85f2872a5680e772647108014ce610db7bfcb7af4a591fea0ebd24361d61b7f2
[root@server1 docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
85f2872a5680 webserver:v1 "/usr/local/nginx/sb..." 4 minutes ago Up 4 minutes 80/tcp web1

查看容器详情
bash
[root@server1 docker]# docker inspect web1

验证部署是否成功
bash
[root@server1 docker]# curl 172.17.0.2
镜像优化
缩减镜像层
bash
#拷贝nginx.conf文件并修改日志路径到终端,便于docker抓取
[root@server1 docker]# vim nginx.conf
error_log /dev/stderr notice;
access_log /dev/stdout main;
[root@server1 docker]# vim Dockerfile
FROM centos:7
RUN rm -f /etc/yum.repos.d/*.repo
COPY CentOS-Base.repo /etc/yum.repos.d/
ADD nginx-1.30.4.tar.gz /mnt/
RUN yum install -y gcc make pcre-devel openssl-devel && cd /mnt/nginx-1.30.4 && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure --with-http_ssl_module --with-http_stub_status_module && make && make install && cd .. && rm -fr nginx-1.30.4 && yum clean all
COPY nginx.conf /usr/local/nginx/conf/
EXPOSE 80
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
[root@server1 docker]# ls
CentOS-Base.repo Dockerfile nginx nginx-1.30.4.tar.gz nginx.conf
[root@server1 docker]# docker build -t webserver:v2 .
[root@server1 docker]# docker images webserver
REPOSITORY TAG IMAGE ID CREATED SIZE
webserver v2 13992a2a16de 54 seconds ago 319MB
webserver v1 e983577bf2ce 42 minutes ago 553MB
[root@server1 docker]# docker run -d --name web1 webserver:v2
a7f6d72d89b9f8894029ff1ec6cd851d47bcb133f0f50d1f21840b1ca3fa919c
[root@server1 docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a7f6d72d89b9 webserver:v2 "/usr/local/nginx/sb..." 22 seconds ago Up 21 seconds 80/tcp web1
[root@server1 docker]# docker rm -f web1
web1
多阶段构建
bash
[root@server1 docker]# vim Dockerfile
FROM centos:7 as build
RUN rm -f /etc/yum.repos.d/*.repo
COPY CentOS-Base.repo /etc/yum.repos.d/
ADD nginx-1.30.4.tar.gz /mnt/
RUN yum install -y gcc make pcre-devel openssl-devel && cd /mnt/nginx-1.30.4 && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure --with-http_ssl_module --with-http_stub_status_module && make && make install && cd .. && rm -fr nginx-1.30.4 && yum clean all
COPY nginx.conf /usr/local/nginx/conf/
FROM centos:7
COPY --from=build /usr/local/nginx /usr/local/nginx
EXPOSE 80
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
[root@server1 docker]# docker build -t webserver:v3 .
[root@server1 docker]# docker images webserver
REPOSITORY TAG IMAGE ID CREATED SIZE
webserver v3 70105c1ba69a 20 seconds ago 205MB
webserver v2 13992a2a16de 6 minutes ago 319MB
webserver v1 e983577bf2ce 47 minutes ago 553MB
[root@server1 docker]# docker run -d --name web1 webserver:v3
53c55976b539716dd9d777b2ade38065c87434f8b506e9bba21b4edec4a515f8
[root@server1 docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
53c55976b539 webserver:v3 "/usr/local/nginx/sb..." 38 seconds ago Up 37 seconds 80/tcp web1
使用最精简的基础镜像
bash
#导入基础镜像
[root@server1 docker]# ls
base-debian12.tar CentOS-Base.repo Dockerfile nginx nginx-1.30.4.tar.gz nginx.conf
[root@server1 docker]# docker load -i base-debian12.tar
[root@server1 docker]# mkdir new
[root@server1 docker]# cd new/
[root@server1 new]# vim Dockerfile
FROM nginx:latest as base
RUN mkdir -p /opt/var/cache/nginx && \
cp -a --parents /usr/lib/nginx /opt && \
cp -a --parents /usr/share/nginx /opt && \
cp -a --parents /var/log/nginx /opt && \
cp -aL --parents /var/run /opt && \
cp -a --parents /etc/nginx /opt && \
cp -a --parents /etc/passwd /opt && \
cp -a --parents /etc/group /opt && \
cp -a --parents /usr/sbin/nginx /opt && \
cp -a --parents /usr/sbin/nginx-debug /opt && \
cp -a --parents /lib/x86_64-linux-gnu/ld-* /opt && \
cp -a --parents /usr/lib/x86_64-linux-gnu/libpcre* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libz.so.* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libc* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libdl* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libpthread* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libcrypt* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libzstd* /opt && \
cp -a --parents /usr/lib/x86_64-linux-gnu/libssl.so.* /opt && \
cp -a --parents /usr/lib/x86_64-linux-gnu/libcrypto.so.* /opt
FROM gcr.io/distroless/base-debian12:latest
COPY --from=base /opt /
EXPOSE 80 443
ENTRYPOINT ["nginx", "-g", "daemon off;"]
[root@server1 new]# docker build -t webserver:v4 .
[root@server1 new]# docker images webserver
REPOSITORY TAG IMAGE ID CREATED SIZE
webserver v4 990537d3b63f 12 seconds ago 62.3MB
webserver v3 70105c1ba69a 6 minutes ago 205MB
webserver v2 13992a2a16de 12 minutes ago 319MB
webserver v1 e983577bf2ce 53 minutes ago 553MB
[root@server1 new]# docker rm -f web1
web1
[root@server1 new]# docker run -d --name web1 webserver:v4
[root@server1 new]# curl 172.17.0.2