Docker镜像原理
docker镜像的本质是一个分层文件系统,Docker 镜像不是一个巨大的单个文件,而是一堆只读的文件层堆叠起来的"千层饼"
-
基础层: 最底层通常是一个精简的操作系统(如 Ubuntu, Alpine)。
-
依赖层: 中间层可能是你安装的运行时环境(如 Python, Java)。
-
应用层: 顶层是你的应用程序代码和配置文件。
一旦镜像构建完成,这些层中的任何文件都不能再被修改

当你下载tomcat镜像时,你其实下载的是rootfs、jdk、tomcat这样一个镜像堆叠系统,这也能解释为什么tomcat镜像比tomcat安装包大很多。
既然镜像的每一层都是绝对只读(Read-Only)的,那容器运行起来之后,程序要写日志、创建新文件(修改镜像)该怎么办?
在容器启动时,Docker 会在镜像的最顶层自动添加一个可写容器container作为可写层,所有对容器的修改,都只发生在这个可写层中
Docker镜像制作
1. 将容器转为镜像
-
docker ps -a :查看所有容器
-
docker images :查看所有镜像
docker commit [选项] 容器ID 新镜像名:版本号
注意:镜像名称必须小写
2. Dockerfile
Dockerfile 是一个文本文件,里面包含了一系列指令,每一条指令构建一层,最终构建出一个新的镜像
# 1. 指定基础镜像(从哪个环境开始)
FROM python:3.9-slim
# 2. 把本地的 app.py 复制到镜像内的 /app 目录
COPY app.py /app/
# 3. 指定容器启动时运行的命令
CMD ["python", "/app/app.py"]
大写的就是指令关键字 ,dockerfile中的指令很多,下面列举一些常用指令:
|------------|-----------------------------|----------------------------------|
| FROM | 指定基础镜像(必须是第一条指令) | FROM ubuntu:22.04 |
| COPY | 复制文件/目录到镜像中 | COPY . /app |
| ADD | 类似 COPY,但支持自动解压 tar 和远程 URL | ADD app.tar.gz /app |
| RUN | 在构建时执行命令(通常用来安装软件、编译代码) | RUN apt-get install -y python3 |
| ENV | 设置环境变量 | ENV NODE_ENV=production |
| EXPOSE | 声明容器监听的端口(只是文档说明) | EXPOSE 8080 |
| CMD | 指定容器启动时运行的默认命令 | CMD ["python", "app.py"] |
如果你需要写dockerfile,建议去DocHub上参考一下代码示例
Docker compose 服务编排
Docker Compose 是一个编排多容器分布式部署的工具,按照一定的业务规则批量管理容器化应用
为什么需要docker compose?
如果没有 Compose ,要运行一个由多个容器组成的应用(比如一个 Web 应用 + Redis + MySQL),每个微服务都需要手动启停、配置他们的端口映射、网络连接。
Docker compose的使用:
-
利用Dockerfile定义运行环境镜像
-
使用docker-compose.yml定义组成应用的各服务
-
运行docker-compose up启动应用
Docker私有仓库
Docker官方的Docker hub是一个用于管理公共镜像的仓库 ,我们可以从上面拉取镜像到本地,也可以把我们的镜像推送上去,如果你不希望把自己的镜像放到公网那你就需要搭建一个私有仓库来管理或存储自己的镜像
私有仓库搭建
拉取私有仓库
docker pull registry
启动私有仓库容器
docker run -id --name=registry -p 5000:5000 registry
修改daemon.json,让 Docker 信任这个私有仓库
vim /etc/docker/daemon.json
# 添加:{"insecure-registries":["私有仓库服务器ip:5000"]}
# 重启服务让配置生效
systemctl restart docker
docker start registry
将镜像上传至私有仓库
#给本地镜像打一个tag,Docker通过镜像的名字来判断要把镜像传到哪里
docker tag centos:7 私有仓库IP:5000/centos:7
#上传标记的镜像
docker push 私有仓库IP:5000/centos:7
第一段代码是给本地镜像创建一个新的标签,告诉Docker这个centos:7镜像将来给我推送到私有仓库去。
这段代码并没有创建一个新的镜像,只是在本地Docker 的镜像数据库 中增加了一个新的引用名称(私有仓库IP:5000/centos:7 ),它指向磁盘上的同一份数据
-
docker tag:Docker 的打标签命令
-
centos:7 :源镜像(本地已有的镜像名和标签)
-
私有仓库IP:5000/centos:7 :目标镜像(新的完整镜像名,包含仓库地址)

第二段代码的作用是:将你本地一个名为私有仓库IP:5000/centos:7 的镜像,上传到你自己的私有 Docker 仓库中

tag就是给镜像起一个包含仓库地址的完整名字,然后docker push就知道往哪传
push命令需要镜像名中包含仓库地址,tag就是用来添加这个地址的