Docker 镜像仓库管理指南
核心概念
镜像仓库是存放Docker镜像的服务器,类似手机应用商店,核心作用是解决镜像的共享与版本管理问题。分为两种类型:
- 公共仓库:如Docker Hub,存放公开镜像
- 私有仓库:企业自建,存放内部镜像
存储结构
- 仓库(Repository)
- 同一类镜像的集合,例如
nginx仓库包含不同版本的nginx镜像。 - 标签(Tag)
- 用于区分同一仓库中的不同镜像版本,例如
nginx:1.23、nginx:latest。 - 镜像 ID
- 镜像的唯一标识,采用 64 位哈希值(通常显示前 12 位),同一标签可能在不同时间指向不同 ID 的镜像。
工作流程
- 推送(push)
- 本地镜像通过
docker push上传到仓库,仓库会验证用户权限并存储镜像的分层数据。 - 拉取(pull)
- 通过
docker pull从仓库下载镜像,Docker 会根据镜像 ID 和分层结构进行增量拉取,仅下载本地缺失的层。 - 缓存机制
- 本地 Docker 引擎会缓存拉取的镜像,避免重复下载,提高效率。
Docker 安装、环境准备(RHEL9)
先检查旧版本,有冲突就卸载旧 docker
⚠️RHEL9 系统自带podman容器工具,podman 和 docker 会发生冲突!必须先卸载 podman,否则 docker 装不上
步骤 1:检查系统自带 podman
rpm -qa | grep podman
从截图查到有两个包:
podman-4.9.4-0.1.el9.x86_64
cockpit-podman-84.1-1.el9.noarch
步骤 2:卸载冲突的 podman(必做!)
dnf remove -y podman cockpit-podman
再查一次,确认删除
步骤 3:切换到 yum 仓库目录,
cd /etc/yum.repos.d/
ls
目录下现有:redhat.repo 、rhel9.repo
步骤 4:,更新镜像仓库:新建 docker 阿里源文件
vim rhel9.repo
粘贴下面内容
保存退出:esc →输入:wq回车
步骤 5:清理缓存,刷新仓库
yum clean all
yum makecache
步骤 6:搜索 docker
dnf search docker
注意我们需要的版本,复制下来
步骤 7:安装 docker‑ce
先给docker创建一个目录作为专属存放位置
cd 回到家目录
进入目录,开始安装刚刚搜索到的docker版本
安装后久能看到包里的东西了
步骤 8:启动 docker,开机自启
systemctl start docker
systemctl enable docker
提示:docker 后台跑 web 服务,默认不需要额外配置防火墙放行容器端口(端口映射后宿主机端口对外)
修改 docker 启动配置、启动服务
yum install -y docker-ce#这个是安装docker,可以省略因为我们前面安装了 #编辑docker服务配置,默认使用iptables vim /usr/lib/systemd/system/docker.service #修改ExecStart增加--iptables=true ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --iptables=true #重启使生效 systemctl daemon‑reload systemctl enable --now docker docker info开启内核路由功能,保障容器网络。
docker 容器做端口映射后,不需要额外配置防火墙即可访问 web 页面(截图 nginx 欢迎页)
一些检查
基本环境配置完成,尝试一些基本操作,看是否成功
使用镜像
这里我创建目录,复制粘贴了一个文件包packages进来,也称之为镜像包,是别人构建好的,后续需要的一些镜像都从这里抽取
#查看本地镜像
[root@Docker-node1 ~]# docker images
本地原来虽然没有game2048.tar.gz镜像,但是packages有game2048.tar.gz镜像这个包,
我们可以导入过来,保存后直接使用
查到所需镜像后,保存镜像到仓库
先开启docker服务再创建服务,
成功。
docker ps查看正在运行容器,看到0.0.0.0:1234->8080/tcp,端口映射生效。
如果本地没有镜像的·话,我们也可以直接搜索——下载,称之为拉取。
拉取镜像有两种情况,一个是在线拉取,一个是离线拉取
| 命令 | 方式 | 数据源 | 条件 |
|---|---|---|---|
docker pull | 在线拉取 | Docker 远程镜像仓库(互联网) | 虚拟机必须能联网,网络不通就失败 |
docker load -i xxx.tar.gz | 离线导入 | 本地磁盘上 tar 压缩包(别人导出好拷贝过来) | 不需要互联网,只要本地有 tar 文件 |
1.在线镜像拉取 + nginx 容器演示
docker pull 镜像名
#搜索镜像 [root@Docker-node1 ~]# docker search nginx NAME DESCRIPTION STARS OFFICIAL nginx Official build of Nginx. 20094 [OK] #从镜像仓库中拉取镜像 [root@Docker-node1 ~]# docker pull busybox [root@Docker-node1 ~]# docker pull nginx:1.26-alpine docker run -d -p 80:80 nginx查看本地的镜像
查看镜像信息
2.离线镜像导入
docker load加载离线 tar 包
docker load -i mario.tar.gz
- `-i`:指定导入的镜像压缩文件
- 输出 `Loaded image: timinglee/mario:latest` → **镜像导入成功,
镜像名:标签 = timinglee/mario:latest
docker 读取 tar 包内部记录,直接还原镜像名 timinglee/mario:latest,这个名字,是打包这个 tar.gz 镜像的人,提前写死在 tar 包内部的,docker load 只是把它读出来,自动恢复。
因此,文件名 ≠ 镜像名
磁盘文件叫 mario.tar.gz,但导入后的镜像名是 timinglee/mario:latest。
timinglee/mario:latest
├── 仓库地址:Docker Hub (docker.io)
├── 命名空间:tminglee(用户/组织)
└── 镜像名:marlo
└── 标签:latest(默认)
3.运行容器
使用镜像创建并运行容器
docker run -d --name marlo -p 1234:8080 tminglee/marlo| 参数 | 含义 |
|---|---|
docker run | 创建并启动一个新容器 |
-d | detach模式,容器在后台运行,不占用当前终端 |
--name marlo | 给容器命名为marlo,方便后续管理 |
-p 1234:8080 | 端口映射,宿主机1234端口 → 容器8080端口 |
tminglee/marlo | 指定使用的镜像名称(来自Docker Hub) |
运行后,如图使用docker ps命令查看容器是否成功运行映射端口
访问本地IP:端口 192.168.1.200:1234,打开超级马里奥网页游戏
容器
基本情况
镜像是把容器永久保存之后的状态
删除容器相关命令
[root@Docker-node1 ~]# docker rm centos7 #删除停止的容器
[root@Docker-node1 ~]# docker rm -f busybox #删除运行的容器
[root@Docker-node1 ~]# docker container prune -f #删除所有停止的容器
系统中的文件和容器中的文件传输
[root@Docker-node1 ~]# docker cp test2:/leefile /mnt #把容器中的文件复制到本机 Successfully copied 1.54kB to /mnt [root@Docker-node1 ~]# docker cp /etc/fstab test2:/fstab #把本机文件复制到容器中运行容器
docker run -it --name test busybox
容器未创建运行前,用--name指定名字为test,busybos是要使用的镜像名称
再次开启
由于这个容器的镜像是一个游戏程序,所以此时显示已在运行
再开一个窗口可以看到该容器已运行
不同容器运行该命令表现不一样
两张图中容器运行反应不同的核心原因在于所使用的 Docker 镜像不同,镜像中包含的应用程序以及启动逻辑的差异导致了交互方式和运行表现的不同。busybox 镜像侧重于提供基础的命令行交互环境,而 timinglee/mario:latest 镜像则侧重于运行特定的应用程序(这里是一个 Web 服务)
---------------------------------------------------------------------------------------------------------------------------------
容器创建后,临时退出想再进去时,可用该命令再次进入终端会话
docker exec -it test sh
- 原理:docker exec命令用于在运行中的 Docker 容器内执行命令。-it选项是-i(保持标准输入打开)和-t(分配一个伪终端)的组合,这样可以提供一个交互式的终端会话。test是容器的名称,sh是要在容器内执行的命令,这里是启动一个 Shell。
- 作用:通过这个命令可以进入正在运行的test容器内部,并且获得一个可以交互操作的 Shell 环境,方便在容器内进行各种操作,比如查看文件、执行脚本等。
ctrl + pq
原理:这是一个快捷键组合,在使用 docker exec -it 进入容器的交互式会话后,按下 Ctrl + p 然后再按下 Ctrl + q,可以实现退出容器但不停止容器的效果。容器会继续在后台运行。
docker load -i busybox-latest.tar.gz
原理:docker load 命令用于从一个 tar 归档文件中加载 Docker 镜像。-i 选项用于指定输入文件,这里是 busybox-latest.tar.gz。当执行这个命令时,Docker 会读取这个 tar 包中的镜像数据,并将其导入到本地的 Docker 镜像仓库中。
作用:将打包好的 Docker 镜像(busybox)加载到本地 Docker 环境中,使其可以被用来创建和运行容器。
如果需要直接删除正在运行的容器,可以使用 -f(force)参数强制删除:
docker rm -f mario
1.如何把容器保存为镜像
2.如何构建镜像
建立构建目录,编写构建文件
注意:拷贝的文件这里是写的相对路径,要么把文件复制到该目录下,要么写它的相对路径
通过dockerfile生成镜像
测试镜像可用性
本地存在名为 lee ,标签为 v1 的镜像 。之前执行 docker run -d --name checkimage lee 报错找不到 lee:latest 镜像,是因为 Docker 默认找 latest 标签镜像,而你本地镜像标签是 v1
可以使用带有 v1 标签的镜像名来运行容器
-d模式启动交互式命令(sh)时,因缺少-it参数导致进程立即退出,只能在docker ps -a中看到。
如果执行命令时提示容器未运行,需要先启动容器:
测试成功,删除容器避免影响其他实验
通过centos容器配置yum源
在容器内部配置,不影响本地仓库
测试能否下载服务
一键配置nginx服务
先配置yum源再配置nginx
[centos7]
name = centos7
baseurl = https://mirrors.aliyun.com/centos/7/os/x86_64/
gpgcheck = 0
删除前面配置的多余的文件
Ps:正常情况下这些rpm包安装后会自动删除,我这里没有自动删除,不影响
运行容器,进入容器内部
容器名 创建的镜像名
Yum源已导入,删除原有的包,否则会冲突
测试yum源是否成功生效
退出容器
实验1:公共仓库操作练习
目标:掌握Docker Hub的镜像推送、拉取和版本管理
ps:公共仓库需要加速器,所以我们这里就简单了解一下,主要做私有仓库
注册Docker Hub账号并完成本地登录(docker login)
基于centos:7构建自定义镜像(例如安装curl),标记格式为用户名/custom-centos:v1:
FROM centos:7 RUN yum install -y curl推送镜像到Docker Hub:
docker push 用户名/custom-centos:v1在另一台机器拉取镜像并验证功能:
docker pull 用户名/custom-centos:v1 docker run --rm 用户名/custom-centos:v1 curl --version更新镜像(例如增加wget)并标记为v2:
FROM centos:7 RUN yum install -y curl wget推送v2版本并观察仓库标签变化
实验2:私有仓库搭建与权限测试
目标:搭建Registry并测试私有镜像的隔离性
在服务器A启动Registry容器(启用insecure访问):
docker run -d -p 5000:5000 \ -v /opt/registry:/var/lib/registry \ --restart=always \ --name registry \ registry:2推送私有镜像到本地仓库:
docker tag centos:7 192.168.1.100:5000/secret-app:v1 docker push 192.168.1.100:5000/secret-app:v1在未配置insecure的服务器B尝试拉取(预期失败):
docker pull 192.168.1.100:5000/secret-app:v1配置服务器B的/etc/docker/daemon.json:
{ "insecure-registries": ["192.168.1.100:5000"] }重启Docker服务后重新拉取验证
实验3:镜像仓库迁移与备份
目标:理解镜像仓库的数据持久化与迁移方法
停止Registry容器并备份数据目录:
docker stop registry tar czvf registry-backup.tar.gz /opt/registry在新服务器恢复数据:
mkdir -p /opt/registry tar xzvf registry-backup.tar.gz -C / docker run -d -v /opt/registry:/var/lib/registry registry:2对比迁移方式差异:
- 使用
docker save导出单镜像:docker save centos:7 > centos7.tar docker load < centos7.tar - 仓库迁移保留全部镜像及层changshichang'shi
其他知识补充
Add和copy的区别案例
创建四个文件并压缩
COPY什么都不做,原原本本的复制,而ADD会帮助解压
如果要在启动容器的同时自动运行指令,或者是启动后,而该指令与变量有关,我们就要先制定变量
构建的时候会显示它正在做什么
CMD和ENTRYPOINT的区别案例
Ps:CMD:启动容器的同时执行命令,如图,启动容器成功后会输出名字lee,但是如果在启动容器的同时执行另一条ls命令,那么echo lee的命令会被覆盖(容器此时已经启动)
、
如果运行时不加别的命令,就会输出CMD指令,如果加了别的指令,cmd就会被覆盖
ENTRYPOINT:与之相反,启动容器的同时执行另一条ls命令,那么echo lee的命令正常输出,不会被覆盖
一键删除
要先删除容器进程才能删除镜像,否则会报错,不过其他的会删除,不影响操作
把未删除的删除
实验出现的一些报错
容器内的第一个进程必须一直处于运行的状态,否则这个容器,就会处于退出状态!