Docker实践学习笔记 1 PostgreSQL和插件的部署 需求:使用docker制作PostgreSQL的镜像并部署,同时需要为其安装postgis,pgrouting和timescaledb插件。
拉取基础镜像postgis/postgis
,该镜像包含了postgres
和postgis
;
1 docker pull postgis/postgis
编写dockerfile
:这里以PostgresSQL 16
为例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 FROM postgis/postgis:latestRUN sed -i 's|http://deb.debian.org/debian|http://mirrors.tencentyun.com/debian|g' /etc/apt/sources.list RUN apt-get update && apt-get install wget RUN wget --quiet -O - https://packagecloud.io/timescale/timescaledb/gpgkey | apt-key add - RUN sh -c "echo 'deb https://packagecloud.io/timescale/timescaledb/ubuntu/ focal main' > /etc/apt/sources.list.d/timescaledb.list" RUN apt-get update && \ apt-get install -y timescaledb-2-2.16.1-postgresql-16 RUN apt-get update && \ apt-get install -y postgresql-$PG_MAJOR -pgrouting CMD ["postgres" ]
说明:
1 2 sed -i 's|http://deb.debian.org/debian|http://mirrors.tencentyun.com/debian|g' /etc/apt/sources.list
^7c1a05
-i
表示直接在原文件中进行修改,而不是将结果输出到标准输出。
's|old|new|g'
s
是 sed
的替换命令,表示将一个字符串替换成另一个字符串。
|
是定界符,通常用 /
作为定界符,但在这里使用了 |
,这在 URL 替换中很常见,因为 URL 中包含 /
,这样可以避免冲突。
g
代表全局替换,表示替换行内所有出现的匹配字符串。如果省略 g
,只会替换每行中第一个匹配的字符串。
最后一个参数是sed
操作的文件
1 sh -c "echo 'deb https://packagecloud.io/timescale/timescaledb/ubuntu/ focal main' > /etc/apt/sources.list.d/timescaledb.list"
^18d0f4
sh -c
是一个 shell 命令,用于执行字符串形式的命令。-c
表示后面跟随的内容是一条完整的命令,传递给 sh
来执行。
1 wget --quiet -O - https://packagecloud.io/timescale/timescaledb/gpgkey | apt-key add -
这条命令用于下载 TimescaleDB 的 GPG 公钥并将其添加到系统的受信任密钥列表中,以便 APT 包管理器能够验证从 TimescaleDB 软件源下载的软件包的真实性和完整性。
wget --quiet -O - https://packagecloud.io/timescale/timescaledb/gpgkey
:
wget
: 是一个用于从网络上下载文件的命令行工具。
--quiet
: 这个选项使 wget
以静默模式运行,不输出下载过程中的信息,仅输出错误和重要消息。
-O -
: 选项 -O
指定将下载的内容输出到某个文件,而不是默认的文件名。-
表示输出到标准输出(通常是终端)。
https://packagecloud.io/timescale/timescaledb/gpgkey
: 这是 TimescaleDB 的 GPG 公钥的 URL。wget
从这个地址下载公钥文件。
apt-key add -
:
apt-key
: 是一个 APT 包管理工具,用于管理 APT 的受信任密钥列表。
add
: 是 apt-key
的一个子命令,用于添加新的密钥到系统的受信任密钥列表中。
-
: 指定从标准输入(即管道)读取密钥数据。apt-key add -
将通过管道传递过来的 GPG 公钥添加到 APT 的受信任密钥列表中。
构建镜像:
1 docker build -t postgres:tag .
创建数据卷,并运行容器:
1 2 3 4 5 6 7 8 9 10 docker volume create pg_data docker run -d \ --name postgres \ -e POSTGRES_USER=admin \ -e POSTGRES_PASSWORD=admin123 \ -e POSTGRES_DB=airport \ -e TZ=Asia/Shanghai \ -p 5432:5432 \ -v pg_data:/var/lib/postgresql/data \ postgres:tag
其中数据卷pg_data
保存postgresql的持久化数据。注意,如果使用目录挂载,数据库、用户和密码设置不会生效。
加载插件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 docker exec -it postgres /bin/bash echo "shared_preload_libraries = 'timescaledb'" >> /var/lib/postgresql/data/postgresql.confdocker restart postgres docker exec -it postgres /bin/bash psql -U admin -d airport create extension pgrouting; create extension timescaledb; select extname from pg_extension;
2 多模块系统部署 描述:现在有一个多模块的系统,即父模块(只有pom管理依赖)下有多个子模块,程序的入口位于子模块admin
中。现在需要打成jar包,并使用docker部署在服务器中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <build > <plugins > <plugin > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-maven-plugin</artifactId > <version > xxx</version > <executions > <execution > <goals > <goal > repackage</goal > </goals > </execution > </executions > </plugin > </plugins > <finalName > xxxx</finalName > </build >
这里的finalName
为打包后jar包的名称。
在admin
目录下执行下列命令,生成可执行jar
包admin.jar
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 FROM openjdk:8 -jreWORKDIR /app ENV TZ=Asia/ShanghaiRUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone COPY admin.jar /admin.jar EXPOSE 8080 ENTRYPOINT ["java" , "-jar" , "admin.jar" ]
将Dockerfile 和jar包 上传至服务器的文件夹中,例如/usr/local/admin
1 2 3 docker build -t admin:tag . docker run -d --name admin -p 8080:8080 admin:tag
3 容器的日志 容器的日志,可以在容器中查看,也可以将日志文件的目录挂载到宿主机的目录上(或数据卷),直接在宿主机上查看。
假设logback
的配置文件如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 <?xml version="1.0" encoding="UTF-8" ?> <configuration > <property name ="log.path" value ="/usr/local/xxx/logs" /> <property name ="log.pattern" value ="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" /> <appender name ="CONSOLE" class ="ch.qos.logback.core.ConsoleAppender" > <encoder > <pattern > ${log.pattern}</pattern > </encoder > </appender > <appender name ="FILE" class ="ch.qos.logback.core.rolling.RollingFileAppender" > <file > ${log.path}/sys_info.log</file > <rollingPolicy class ="ch.qos.logback.core.rolling.TimeBasedRollingPolicy" > <fileNamePattern > ${log.path}/sys_info.%d{yyyy-MM-dd}.%i.log</fileNamePattern > <maxHistory > 30</maxHistory > <timeBasedFileNamingAndTriggeringPolicy class ="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP" > <maxFileSize > 10MB</maxFileSize > </timeBasedFileNamingAndTriggeringPolicy > </rollingPolicy > <encoder > <pattern > ${log.pattern}</pattern > </encoder > </appender > <root level ="info" > <appender-ref ref ="CONSOLE" /> <appender-ref ref ="FILE" /> </root > </configuration >
其中,日志文件的输出位置位于/usr/local/xxx/logs
。
如果Dockerfile
没有另外设置WORKDIR
,则日志位于容器的上述目录,可进入容器中查看:
1 2 3 4 5 6 7 8 9 docker exec -it <container_id> /bin/bash cd /usr/local/xxx/logscat sys_info.log
如果设置了WORKDIR
,假设为app
,则:
1 2 3 4 5 6 7 8 9 docker exec -it <container_id> /bin/bash cd app/usr/local/xxx/logscat sys_info.log
1 docker run -d --name xxxx -v /usr/local/xxx/logs:/usr/local/xxx/logs xxx:latest
则可以在宿主机中直接查看日志:
1 2 3 cd /usr/local/xxx/logscat sys_info.log
同样的,如果设置了WORKDIR
,假设为app
,则:
1 2 3 4 5 docker run -d --name xxxx -v /usr/local/xxx/logs:app/usr/local/xxx/logs xxx:latest cd /usr/local/xxx/logscat sys_info.log
4 离线安装Docker
下载 Docker 安装包: 从 Docker 官方网站 下载适合 Docker 安装包(中科大镜像源 )
一般来说,需要下载以下文件:
1 2 3 4 containerd.io_<version>_<arch>.deb docker-ce_<version>_<arch>.deb docker-ce-cli_<version>_<arch>.deb docker-compose-plugin_<version>_<arch>.deb
其中arch
的查看方法详见:[[处理器架构#1 查看]]
1 2 3 4 5 systemctl start docker systemctl enable docker systemctl status docker
从 Docker Compose 发布页面 下载 Docker Compose 二进制文件。
1 cp docker-compose-<version> /usr/local/bin/docker-compose
1 chmod +x /usr/local/bin/docker-compose
1 docker-compose --version
在安装Docker的过程中,可能会出现错误:
1 groupadd:无法打开 /etc/group
该错误的原因是因为对系统的关键文件进行了锁定,防止篡改,可以通过以下命令查看是否锁定:
如果显示:
1 ----i---------- /etc/group
权限 i
表示该文件不能被删除、改名、设定链接关系,同时不能写入或新增内容。
可执行下列执行暂时放开权限:
1 2 chattr -i /etc/group chattr -i /etc/gshadow
安装完成后,可再执行以下命令恢复配置:
1 2 chattr +i /etc/group chattr +i /etc/gshadow
5 应用更新 问题描述:Docker部署springboot应用时,怎么设置才能避免每次更新jar包时,需要重新构建镜像?
1 2 3 4 5 6 7 8 9 FROM openjdk:8 -jreWORKDIR var/lib/app/ EXPOSE 8082 CMD ["java" , "-jar" , "var/lib/app/application.jar" ]
构建镜像:
1 docker build -t application .
使用docker-compose
部署多个docker容器,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 services: sgis-postgis: image: postgres-timescale:15 container_name: postgis volumes: - "../postgres/data:/var/lib/postgresql/data/" ports: - "5432:5432" networks: - sgis_network restart: always rabbitmq: image: rabbitmq:latest container_name: rabbitmq ports: - "5672:5672" - "15672:15672" volumes: - "../rabbitmq:/var/lib/rabbitmq" environment: - RABBITMQ_DEFAULT_USER: "fisher" - RABBITMQ_DEFAULT_PASS: "fisher" networks: - sgis_network restart: always redis: image: redis:latest container_name: redis ports: - "6379:6379" networks: - sgis_network command: --save 60 1 --loglevel warning restart: always tomcat: image: "tomcat:latest" container_name: tomcat privileged: true environment: - TZ="Asia/Shanghai" ports: - "9016:8080" networks: - sgis_network volumes: - "../tomcat/webapps:/usr/local/tomcat/webapps" restart: always application: image: application:latest container_name: application ports: - "8082:8082" volumes: - "../app/application.jar:/var/lib/app/application.jar" networks: - sgis_network restart: always depends_on: - sgis-postgis - rabbitmq - redis networks: sgis_network: driver: bridge
其中../app/application.jar
为本地的jar文件存放位置,/var/lib/app/application.jar
为容器内jar的存放位置
使用命令启动多个容器:
当jar更新时,首先停止并删除原来的application
容器,然后替换原有的jar包,最后重启:
1 2 3 4 docker rm -f application
6 Overlay2 Docker 使用了多种文件系统驱动(Storage Drivers)来管理镜像和容器的存储。这些文件系统提供了分层存储机制,使 Docker 能高效地构建和运行容器。
查看Docker的文件系统驱动:
1 2 3 docker info | grep "Storage Driver" Storage Driver: overlay2
Overlay 文件系统(OverlayFS)是一种现代的联合文件系统(Union Filesystem),最初由 Linux 内核社区引入,用于高效管理文件和目录的分层。Docker 利用 OverlayFS 实现了镜像和容器的分层文件系统,是其默认的存储驱动之一(尤其是 overlay2
驱动)。
6.1 层(Layer) Docker 的层是一个只读文件系统,它记录了镜像或容器的文件系统变化。每一层都建立在其下层之上,形成了分层的存储结构。
特点:
增量存储:每一层只存储相对于上一层的差异。
只读:所有的层均为不可变的。
可共享:多个镜像或容器可以共享相同的层。
6.1.1 层的组成 基础层(Base Layer):
是镜像的最底层,通常包含一个操作系统的最小安装包(如 Ubuntu、Alpine)。
基础层提供了运行应用程序所需的基本环境。
中间层(Intermediate Layer):
每次在 Dockerfile 中执行指令(如 RUN
、COPY
、ADD
)时,都会创建一个新的层。
中间层记录了该指令所引入的更改。
可写层(Writable Layer):
容器启动时,Docker 在镜像层之上添加一个可写层。
容器中的所有文件写操作(新增、修改或删除)都发生在这一层。
6.1.2 层的存储路径 在 Docker 中,层的实际存储取决于所使用的存储驱动:
OverlayFS:
每一层存储在 /var/lib/docker/overlay2/
目录下。
每个层会有一个唯一的目录,包含层的元数据和文件。
AUFS、devicemapper 等其他驱动:
6.1.3 Layer、Image和Container
1 2 3 4 5 6 7 8 9 10 镜像: Layer 1 (基础层,如操作系统) + Layer 2 (运行时环境,如 Python) + Layer 3 (应用文件) 容器: Layer 1 (共享的基础层) + Layer 2 (共享的运行时环境) + Layer 3 (共享的应用文件) + Writable Layer (容器的可写层,存储运行时的动态更改)
镜像
镜像是多个层的有序集合,是一种静态的文件系统快照。
镜像可以被多次重用,多个容器可以基于同一个镜像创建。
通过 Dockerfile 构建镜像时,每条指令(如 RUN
、COPY
)都会创建一个新层。
容器
容器是镜像的一个实例,运行时包含镜像的内容以及一个额外的可写层。
每个容器有自己的文件系统和网络环境,但共享镜像层。
容器的可写层是临时的,容器删除后更改会丢失(除非通过卷或持久化存储)。
容器启动时,Docker 将镜像层和容器的可写层组合在一起,形成一个联合文件系统。
6.2 工作原理 OverlayFS 将两个目录(称为下层和上层)叠加在一起,显示为一个单一的目录(称为叠加层)。
下层(lowerdir):
上层(upperdir):
工作目录(workdir):
OverlayFS 的临时工作目录,用于存储文件系统操作(如文件的写入和删除)的中间状态。
6.3 存储过程 层:直接存储。
镜像:Docker 镜像由多个只读层组成,每一层代表了一次镜像构建中的更改。OverlayFS 将这些只读层视为多个 lowerdir
,通过叠加形成一个完整的文件系统视图。
容器:每个容器都会在镜像层之上添加一个可写层(upperdir
)。容器运行时,所有文件的修改都发生在这个可写层中。
当使用 OverlayFS 时,Docker 的存储目录(如 /var/lib/docker/overlay2
)包含以下子目录:
diff/
: 存储每个层的实际文件数据。
merged/
: 存储叠加后的文件系统视图,容器运行时可见。
upper/
: 存储容器的可写层(仅针对运行的容器)。
work/
: 用于 OverlayFS 的中间操作。
镜像的存储
1 2 3 4 [root@kube1 overlay2]# ll total 0 brw------- 1 root root 253, 0 Jan 27 22:04 backingFsBlockDev drwx------ 2 root root 6 Jan 27 22:04 l
可以看到/var/lib/docker/overlay2
目录只有backingFsBlockDev
和l
两个目录。
1 2 3 4 5 6 7 8 9 10 11 12 13 [root@kube1 overlay2]# docker pull nginx Using default tag: latest latest: Pulling from library/nginx 2f44b7a888fa: Pull complete 8b7dd3ed1dc3: Pull complete 35497dd96569: Pull complete 36664b6ce66b: Pull complete 2d455521f76c: Pull complete dc9c4fdb83d6: Pull complete 8056d2bcf3b6: Pull complete Digest: sha256:4c0fdaa8b6341bfdeca5f18f7837462c80cff90527ee35ef185571e1c327beac Status: Downloaded newer image for nginx:latest docker.io/library/nginx:latest
可以看到目前版本的Nginx镜像一共被分为7层拉取。
进入/var/lib/docker/overlay2/
目录,发现多了7个目录,对应7个层
1 2 3 4 5 6 [root@kube1 overlay2]# ls 10dd8ff4345f0387e720d5fdd1df6c6d2b73547d912d139868afd7835ff83503 backingFsBlockDev 2839c8c9efc53d0d0a89611b08d2ecead4717031e2458efe8721e2ec0007d7b1 c2f6ab870d00b7709f1745e0373fa6eb7f90cec78348d36b66ba57c3108045a0 410fc9512d1e11b714b6643ce2dcd987df56cc0025b4133afb4645f865757584 cb9d1b97aade9bd3e3a56268a8608622a86a7ac0d0ade9bbb2b0679f4c0ed620 48305d303096d54e0eea026f3366357e2c485c7d5b7c5939e5a062cc36bd03b2 l a593596d98137556641a7376b14a4d0b00f6f2d6f05bdffe05b01d740a65e894
查看Nginx镜像信息,可以看到镜像的每个层的存储位置GraphDriver.Data
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 "GraphDriver" : { "Data" : { "LowerDir" : "/var/lib/docker/overlay2/48305d303096d54e0eea026f3366357e2c485c7d5b7c5939e5a062cc36bd03b2/diff:/var/lib/docker/overlay2/cb9d1b97aade9bd3e3a56268a8608622a86a7ac0d0ade9bbb2b0679f4c0ed620/diff:/var/lib/docker/overlay2/10dd8ff4345f0387e720d5fdd1df6c6d2b73547d912d139868afd7835ff83503/diff:/var/lib/docker/overlay2/410fc9512d1e11b714b6643ce2dcd987df56cc0025b4133afb4645f865757584/diff:/var/lib/docker/overlay2/a593596d98137556641a7376b14a4d0b00f6f2d6f05bdffe05b01d740a65e894/diff:/var/lib/docker/overlay2/c2f6ab870d00b7709f1745e0373fa6eb7f90cec78348d36b66ba57c3108045a0/diff" , "MergedDir" : "/var/lib/docker/overlay2/2839c8c9efc53d0d0a89611b08d2ecead4717031e2458efe8721e2ec0007d7b1/merged" , "UpperDir" : "/var/lib/docker/overlay2/2839c8c9efc53d0d0a89611b08d2ecead4717031e2458efe8721e2ec0007d7b1/diff" , "WorkDir" : "/var/lib/docker/overlay2/2839c8c9efc53d0d0a89611b08d2ecead4717031e2458efe8721e2ec0007d7b1/work" }, "Name" : "overlay2" }, "RootFS" : { "Type" : "layers" , "Layers" : [ "sha256:571ade696b261f0ff46e3cdac4635afc009c4ed3429950cb95cd7e5f70ba0a07" , "sha256:b6c2a8d6f0ac89ef77e161532f3d9d0dc5dfe0a5f20042e0afc0ad14288405eb" , "sha256:b61d4b2cd2daf06047984c5876a35338c2beb5ae3f6bef479d25f05772a6a482" , "sha256:eddcd06e5ef9b91677526f6c55fa01a7d6963c435d5cf2bfb488d91aaa72d4a8" , "sha256:b4ad478450363f0a8020bb5552641fe6077e78fca48da4d77a979724a3ad2a72" , "sha256:fbcc9bc44d3e165e7e4f56fb189a05ea5c562a733985ec00d5e3fad309eb63cc" , "sha256:009507b8560964795eab5126f6363cb2b7403596adf370c9e95d4648c43e771f" ] }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 [root@kube1 overlay2]# ls */ 10dd8ff4345f0387e720d5fdd1df6c6d2b73547d912d139868afd7835ff83503/: committed diff link lower work 2839c8c9efc53d0d0a89611b08d2ecead4717031e2458efe8721e2ec0007d7b1/: diff link lower work 410fc9512d1e11b714b6643ce2dcd987df56cc0025b4133afb4645f865757584/: committed diff link lower work 48305d303096d54e0eea026f3366357e2c485c7d5b7c5939e5a062cc36bd03b2/: committed diff link lower work a593596d98137556641a7376b14a4d0b00f6f2d6f05bdffe05b01d740a65e894/: committed diff link lower work c2f6ab870d00b7709f1745e0373fa6eb7f90cec78348d36b66ba57c3108045a0/: committed diff link cb9d1b97aade9bd3e3a56268a8608622a86a7ac0d0ade9bbb2b0679f4c0ed620/: committed diff link lower work l/: D6T76WE7CR4JMMPUM4NTO55AXG JMSMKE6MVY4KJ5CB5ZDDIDVPW2 SX6PROXGAB4ZJPH7HTPYRQUMH2 WCBZTXQX2YLYEZWCUYGFHKTAST GTRRPSN3NBPKHCIMECN7X7BJEP LHNRUYWVMA3S5JGMBYRKW4BWHI TMLMOWKXKUJ4WAWMNDCJVVLMBG
可以看到c2f6ab870d00b7709f1745e0373fa6eb7f90cec78348d36b66ba57c3108045a0
文件夹中不存在lower文件,说明它是最底层的,相当于是根镜像,即docker pull时下载的第一层。
总结:拉取一个镜像时,会按照镜像的层在/var/lib/docker/overlay2
下新增相应的目录。
容器的存储
当前环境只有一个nginx镜像,没有容器,/var/lib/docker/overlay2/
目录下只有镜像层的存储目录。
启动一个容器
1 2 3 4 5 [root@kube1 overlay2]# docker run -id nginx 76cd5f0f5a3f8969d3061dfc94107858f4ae4e9c5634320347c8650528434e87 [root@kube1 overlay2]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 76cd5f0f5a3f nginx "/docker-entrypoint.…" 3 seconds ago Up 2 seconds 80/tcp festive_lederberg
查看/var/lib/docker/overlay2/
目录,发现新增了两个目录:其中带-init的目录是只读的;没有init的容器目录才是容器的读写目录
1 2 3 4 5 6 7 8 9 10 11 12 [root@kube1 overlay2]# ll total 0 drwx--x--- 4 root root 72 Jan 27 22:12 10dd8ff4345f0387e720d5fdd1df6c6d2b73547d912d139868afd7835ff83503 drwx--x--- 4 root root 72 Jan 28 01:10 2839c8c9efc53d0d0a89611b08d2ecead4717031e2458efe8721e2ec0007d7b1 drwx--x--- 4 root root 72 Jan 27 22:12 410fc9512d1e11b714b6643ce2dcd987df56cc0025b4133afb4645f865757584 drwx--x--- 4 root root 72 Jan 27 22:12 48305d303096d54e0eea026f3366357e2c485c7d5b7c5939e5a062cc36bd03b2 drwx--x--- 4 root root 72 Jan 27 22:12 a593596d98137556641a7376b14a4d0b00f6f2d6f05bdffe05b01d740a65e894 brw------- 1 root root 253, 0 Jan 27 22:04 backingFsBlockDev drwx--x--- 3 root root 47 Jan 27 22:12 c2f6ab870d00b7709f1745e0373fa6eb7f90cec78348d36b66ba57c3108045a0 drwx--x--- 5 root root 69 Jan 28 01:10 cb03d50e1baaf7e40f3c981c428213cef7a3b375d7d9134cc3db932fd94b9bcb drwx--x--- 4 root root 72 Jan 28 01:10 cb03d50e1baaf7e40f3c981c428213cef7a3b375d7d9134cc3db932fd94b9bcb-init drwx--x--- 4 root root 72 Jan 27 22:12 cb9d1b97aade9bd3e3a56268a8608622a86a7ac0d0ade9bbb2b0679f4c0ed620
此外,容器id和该目录的名称并不一致。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 [root@kube1 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 76cd5f0f5a3f nginx "/docker-entrypoint.…" 26 minutes ago Up 26 minutes 80/tcp festive_lederberg [root@kube1 ~]# docker inspect 76 "GraphDriver" : { "Data" : { "LowerDir" : "/var/lib/docker/overlay2/cb03d50e1baaf7e40f3c981c428213cef7a3b375d7d9134cc3db932fd94b9bcb-init/diff:/var/lib/docker/overlay2/2839c8c9efc53d0d0a89611b08d2ecead4717031e2458efe8721e2ec0007d7b1/diff:/var/lib/docker/overlay2/48305d303096d54e0eea026f3366357e2c485c7d5b7c5939e5a062cc36bd03b2/diff:/var/lib/docker/overlay2/cb9d1b97aade9bd3e3a56268a8608622a86a7ac0d0ade9bbb2b0679f4c0ed620/diff:/var/lib/docker/overlay2/10dd8ff4345f0387e720d5fdd1df6c6d2b73547d912d139868afd7835ff83503/diff:/var/lib/docker/overlay2/410fc9512d1e11b714b6643ce2dcd987df56cc0025b4133afb4645f865757584/diff:/var/lib/docker/overlay2/a593596d98137556641a7376b14a4d0b00f6f2d6f05bdffe05b01d740a65e894/diff:/var/lib/docker/overlay2/c2f6ab870d00b7709f1745e0373fa6eb7f90cec78348d36b66ba57c3108045a0/diff" , "MergedDir" : "/var/lib/docker/overlay2/cb03d50e1baaf7e40f3c981c428213cef7a3b375d7d9134cc3db932fd94b9bcb/merged" , "UpperDir" : "/var/lib/docker/overlay2/cb03d50e1baaf7e40f3c981c428213cef7a3b375d7d9134cc3db932fd94b9bcb/diff" , "WorkDir" : "/var/lib/docker/overlay2/cb03d50e1baaf7e40f3c981c428213cef7a3b375d7d9134cc3db932fd94b9bcb/work" }, "Name" : "overlay2" } }
当进入容器创建一个文件,然后在容器相应的merged目录也会出现这个文件。
1 2 3 4 5 6 7 8 [root@kube1 ~]# docker exec -it 76 /bin/bash root@76cd5f0f5a3f:/# ls bin boot dev docker-entrypoint.d docker-entrypoint.sh etc home lib lib32 lib64 libx32 media mnt opt proc root run sbin srv sys tmp usr var root@76cd5f0f5a3f:/# touch a.txt root@76cd5f0f5a3f:/# exit [root@kube1 merged]# pwd /var/lib/docker/overlay2/cb03d50e1baaf7e40f3c981c428213cef7a3b375d7d9134cc3db932fd94b9bcb/merged [root@kube1 merged]# ls a.txt
总结:运行一个容器的时候,会在/var/lib/docker/overlay2
下新增两个目录(-init
区分),容器实际运行数据存储在该目录下的merged
目录中。