容器大王Docker——玩转docker(上)
上文介绍的是1.什么是Docker,2.部署docker,3.Docker的基本操作,4.docker镜像构建,5.搭建docker私有仓库以及企业级私有仓库harbor,后续请关注下篇
一 Docker简介
1.1 什么是docker?
官方站点:https://docs.docker.com/

要理解什么是Docker就先明白为什么需要 Docker?(核心痛点)
在 Docker 出现前,开发和运维常面临 “环境不一致” 的噩梦:
- 开发电脑上:Windows/macOS 系统,安装了 Python 3.8、MySQL 5.7,依赖库版本精确匹配,代码跑得很顺畅。
- 测试 / 生产服务器上:Linux 系统,可能预装了 Python 3.6、MySQL 8.0,甚至缺少某个隐藏依赖,导致代码报错、功能失效。
- 本质原因:软件运行需要 “操作系统内核 + 系统库 + 依赖包 + 配置” 的完整环境,不同机器的环境差异会打破运行一致性。
Docker 的解决方案是:把软件和它依赖的 “最小环境” 一起打包成一个独立的 “容器”,这个容器能在任何支持 Docker 的机器上 “原样运行”,无需再手动配置环境。
Docker 的核心概念:3 个关键组件

要理解 Docker,必须先掌握它的 3 个核心概念,它们是 Docker 工作的基础:
| 概念 | 核心作用 | 类比(生活化理解) |
|---|---|---|
| 镜像(Image) | 软件的 “安装包” 或 “模板”,包含运行软件所需的所有文件(代码、依赖、配置、系统库) | 手机 App 的 “安装包(.apk/.ipa)” |
| 容器(Container) | 镜像的 “运行实例”,是一个独立的、可执行的环境(镜像加载后在内存中形成的进程) | 手机上 “已安装并正在运行的 App” |
| 仓库(Repository) | 存储和分发镜像的 “仓库”,类似代码仓库(如 GitHub) | 手机的 “应用商店(App Store)” |
概念间的关系(流程):
- 开发者在本地编写代码,然后将 “代码 + 依赖环境” 打包成 镜像;
- 将镜像上传到 仓库(如 Docker Hub,官方公共仓库);
- 运维人员从仓库下载镜像,在服务器上启动镜像,生成 容器(软件开始运行)。
整个过程中,“镜像” 是 “不变的模板”,“容器” 是 “可变的运行实例”—— 比如一个 Nginx 镜像,可以启动 10 个容器,对应 10 个独立的 Nginx 服务。
1.2 Docker与传统虚拟机区别
Docker 不是虚拟机!(关键区别)
很多人会把 Docker 和虚拟机(VM,如 VMware、VirtualBox)混淆,但两者的底层原理完全不同,效率差距极大:

| 对比维度 | Docker(容器) | 传统虚拟机(VM) |
|---|---|---|
| 底层依赖 | 共享宿主机的操作系统内核(仅模拟用户空间) | 虚拟完整的操作系统(内核 + 用户空间) |
| 资源占用 | 极轻量(MB 级),启动快(秒级) | 重量级(GB 级),启动慢(分钟级) |
| 隔离性 | 进程级隔离(隔离性中等) | 系统级隔离(隔离性极强) |
| 适用场景 | 部署微服务、应用打包、环境一致性保障 | 运行不同内核的系统(如 Windows 跑 Linux) |
简单说:虚拟机是 “模拟一台完整电脑”,而 Docker 是 “模拟一个独立的应用进程”—— 前者资源开销大,后者轻量高效,更适合现代软件部署。
1.3 Docker 的核心优势
- 环境一致性:“一次构建,到处运行”,彻底解决 “开发能跑,生产报错” 的问题。
- 轻量高效:容器共享宿主机内核,启动快、占用资源少,一台服务器可运行成百上千个容器。
- 隔离性:每个容器是独立的 “沙箱”,进程、文件、网络互不干扰(比虚拟机弱,但满足大部分场景)。
- 易于扩展:支持快速复制容器(如 1 个 Nginx 容器扩展到 10 个),配合 Kubernetes(K8s)可实现自动化扩缩容。
- 版本控制:镜像支持版本管理(如
nginx:1.21、nginx:1.22),可快速回滚到历史版本。
1.4 Docker 的常见应用场景
-
开发环境统一:团队成员通过 Docker 镜像获取一致的开发环境,无需手动配置依赖(比如前端的 Node.js 环境、后端的 Java 环境)。
-
微服务部署:现代微服务架构(如 Spring Cloud、K8s)的基础 —— 每个微服务打包成一个镜像,独立部署、升级。
-
持续集成 / 持续部署(CI/CD):在自动化流水线中,用 Docker 打包应用,然后自动部署到测试 / 生产环境。
-
快速测试:启动一个临时容器测试新功能,测试完成后直接删除,不污染宿主机环境(如测试不同版本的数据库)。

- 在企业中docker作为业务的最小载体而被广泛应用
- 通过docker企业可以更效率的部署应用并更节省资源
[!NOTE]
IaaS(Infrastructure as a Service),即基础设施即服务
PaaS是(Platform as a Service)即指平台即服务
SaaS(Software as a Service)软件运营服务是
二 部署docker
1.配置软件仓库,安装docker
[root@docker-node1 ~]# vim /etc/yum.repos.d/docker.repo
[docker-ce]
name = docker-ce
baseurl = https://mirrors.aliyun.com/docker-ce/linux/rhel/9/x86_64/stable/
gpgcheck = 0
2.删除redhat系统自带的podman,防止与docker冲突
[root@docker-node1 ~]# rpm -qa | grep podman
podman-4.9.4-0.1.el9.x86_64
cockpit-podman-84.1-1.el9.noarch
3.安装docker-ce并启动服务
[root@docker-node1 ~]# dnf install docker-ce.x86_64 -y
[root@docker-node1 ~]# systemctl enable --now docker
#查看docker详细信息
[root@docker-node1 ~]# docker info
4.docker初始化设置,激活内核网络选项
#编辑docker启动文件,设定其使用iptables的网络管理设定方式,默认使用nftables
[root@docker-node1 ~]# vim /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --iptables=true
[root@docker-node1 ~]# systemctl daemon-reload
[root@docker-node1 ~]# systemctl restart docker
#以下操作只要在rhel7上做
]# echo br_netfilter > /etc/modules-load.d/docker_mod.conf
]# modprobe br_netfilter
]# vim /etc/sysctl.d/docker.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
#rhel9只需要打开内核路由功能,因为容器在运行时是通过桥接模式连接真实主机
[root@docker-node1 ~]# echo net.ipv4.ip_forward = 1 >> /etc/sysctl.conf
[root@docker-node1 ~]# sysctl -p
net.ipv4.ip_forward = 1
三 Docker的基本操作
1.docker镜像命令基本操作
1.从镜像仓库搜索镜像
#docker默认镜像仓库是docker.io,使用docker的镜像仓库需要VPN加速
[root@Docker-node1 ~]# docker search nginx
NAME DESCRIPTION STARS OFFICIAL
nginx Official build of Nginx. 20094 [OK]
| 参数 | 说明 |
|---|---|
| NAME | 镜像名称 |
| DESCRIPTION | 镜像说明 |
| STARS | 点赞数量 |
| OFFICIAL | 是否是官方的 |
2.从镜像仓库拉取镜像
[root@Docker-node1 ~]# docker pull busybox
[root@Docker-node1 ~]# docker pull nginx:1.26-alpine #alpine版本,nginx镜像的最小安装发行版本
3.导入与导出镜像
#导入镜像到本地
[root@docker-node1 ~]# docker load -i nginx-latest.tar.gz
#导出镜像
[root@docker-node1 ~]# docker save -o fjw.tar nginx:latest timinglee/game2048:latest
#当本地镜像比较多时,可以使用awk来全部导出
[root@docker-node1 ~]# docker save -o yyy.tar `docker images | awk 'NR>1{print $1":"$2}'`
[!NOTE]
-i:input,用于导入镜像;
-o:output;
1.用于指定导出镜像的位置;
2.可以同时导出多个镜像到一个文件中;
3.指定.tar可以导出并打包。
4.查看本地镜像与详细信息
#查看本地镜像
[root@docker-node1 packages]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 5ef79149e0ec 11 months ago 188MB
busybox latest 65ad0d468eb1 2 years ago 4.26MB
centos 7 eeb6ee3f44bd 3 years ago 204MB
#查看镜像详细信息
[root@docker-node1 packages]# docker image inspect busybox:latest
[root@docker-node1 packages]# docker inspect centos:7
5.删除镜像
[root@docker-node1 packages]# docker rmi nginx:latest
#通过``优先执行里面的内容通过awk来删除所有的本地镜像,当本地镜像较多时可以一次性删除
[root@docker-node1 packages]# docker rmi `docker images | awk 'NR>1{print $1":"$2}'`
2.docker容器命令基本操作
1.启动容器
[!NOTE]
容器命令参数
-d #后台运行 -i #交互式运行 -t #打开一个终端 --name #指定容器名称 -p #端口映射 -p 80:8080 把容器8080端口映射到本机80端口 --rm #容器停止自动删除容器 --network #指定容器使用的网络,容器默认使用桥接网络;可以改为host,none等
#-d后台运行一个容器,-p 1234:8080把容器8080端口映射到本机1234端口
[root@docker-node1 ~]# docker run -d --name mario -p 1234:8080 timinglee/mario:latest
#运行一个使用shell交互的容器,-it:与容器进行终端交互,-i表示保持标准输入打开,-t表示分配一个伪终端
[root@Docker-node1 ~]# docker run -it --name centos centos:7
[root@3ba22e59734f /]#
#进入到容器中,按<ctrl>+<d>退出并停止容器,#按<ctrl>+<pq>退出但不停止容器
#容器开启后没停止在后台运行时
#当退出容器后没停止容器,可以使用attach重新与容器交互
[root@docker-node1 ~]# docker attach centos
#当退出容器后没停止容器,也可以使用docker exec -it 指定shell创建一个新进程重新进入容器交互
[root@docker-node1 ~]# docker exec -it centos bash/sh
#如果容器停止了可以start开启容器进行交互运行
[root@docker-node1 ~]# docker start mario
#可以在容器中执行命令
[root@docker-node1 packages]# docker exec -it centos ls
anaconda-post.log bin dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
[!WARNING]
有些镜像开启容器没有后台驻守程序,在运行时不加-it参数运行后会关闭!!
有驻守程序不加-it参数的话会占用当前终端
运行应用服务器或web服务器端口映射的默认会使用除shell外的驻守程序;
如果使用shell为驻守程序会导致服务不可用

2.查看容器运行信息
[root@Docker-node1 ~]# docker ps #查看当前运行容器
[root@Docker-node1 ~]# docker ps -a #查看所有容器,包括停止的容器
[root@Docker-node1 ~]# docker inspect busybox #查看容器运行的详细信息
3.停止和运行容器
[root@docker-node1 ~]# docker start mario #停止容器
[root@Docker-node1 ~]# docker kill busybox #杀死容器,可以使用信号
[root@docker-node1 ~]# docker stop mario #开启停止的容器
[!NOTE]
容器内的第一个进程必须一直处于运行的状态,否则这个容器,就会处于退出状态!
4.删除容器
[root@Docker-node1 ~]# docker rm centos7 #删除停止的容器
[root@Docker-node1 ~]# docker rm -f busybox #删除运行的容器
[root@Docker-node1 ~]# docker container prune -f #删除所有停止的容器
5.容器内容提交
默认情况下,容器被删除后,在容器中的所有操作都会被清理,包括要保存的文件;
如果想永久保存,那么我们需要把动作提交,提交后会生成新的镜像;
当我们在运行新镜像后即可看到我们提交的内容。
[root@docker-node1 docker]# docker run -it --name test busybox:latest
/ # touch testfile #在容器中建立文件
/ # ls
bin dev etc home lib lib64 proc root sys testfile tmp usr var
/ # exit
[root@docker-node1 docker]# docker rm test #删掉容器后开启新的容器文件不存在
test
[root@docker-node1 docker]# docker run -it --name test busybox:latest
/ # ls
bin dev etc home lib lib64 proc root sys tmp usr var
/ # touch testfile #想要永久保存
/ # ls
bin dev etc home lib lib64 proc root sys testfile tmp usr var
/ # [root@docker-node1 docker]# #退出不停止容器<ctl><p+q>
#使用commit命令来提交内容,构建一个镜像
[root@docker-node1 docker]# docker commit -m "add testfile" test busybox:testv1
[root@docker-node1 docker]# docker images
busybox testv1 bc50de975732 6 seconds ago 4.26MB
[root@docker-node1 docker]# docker image history busybox:testv1
IMAGE CREATED CREATED BY SIZE COMMENT
bc50de975732 30 seconds ago sh 21B add testfile
65ad0d468eb1 2 years ago BusyBox 1.36.1 (glibc), Debian 12 4.26MB
[!NOTE]
此方法不利于企业审计,所以不推荐使用,在企业中我们多用Dockerfile来构建镜像
6.系统与容器之间的文件传输
#把容器中的文件复制到本机
[root@docker-node1 docker]# docker cp test:/etc/hosts /root/docker/
#把本机文件复制到容器中
[root@docker-node1 docker]# docker cp ./centos.repo test:/etc
7.查询容器内部日志
[root@docker-node1 docker]# docker logs test
/ # ls
bin dev etc home lib lib64 proc root sys tmp usr var
/ # touch testfile
/ # ls
bin dev etc home lib lib64 proc root sys testfile tmp usr var
/ #
/ #
/ # ls
bin dev etc home lib lib64 proc root sys testfile tmp usr var
/ #
/ # cd etc/
/etc # ;s
sh: syntax error: unexpected ";"
/etc # ls
group hosts mtab nsswitch.conf resolv.conf
hostname localtime network passwd shadow
/etc # ls
centos.repo hostname localtime network passwd shadow
group hosts mtab nsswitch.conf resolv.conf
/etc # cat centos.repo
[centos]
name = centos
baseurl = https://mirrors.aliyun.com/centos/7/os/x86_64/
gpgcheck = 0
四 docker镜像构建
1.构建参数
| FROM | 指定源镜像 |
|---|---|
| COPY | 复制文件 |
| MAINTAINER | 指定作者信息,最新版docker已经用LABEL KEY="VALUE"代替 |
| ADD | 功能与copy相似,区别就是在添加压缩包时,add是解包后再添加进容器;而copy是直接添加压缩包不提供解包功能 |
| ENV | 变量,指定环境变量 eg: ENV FILENAME test |
| EXPOSE | 暴露容器端口 |
| VOLUME | 申明数据卷,通常指数据挂载点 |
| WORKDIR | 进入容器时切换路径 |
| RUN | 在镜像构建过程运行指令存入镜像中 |
| CMD | 在启动容器后执行的一个命令,eg: echo $FILENAME 会调用shell解析,显示在当前终端 |
| ENTRYPOINT | 和CMD功能和用法类似,但动作不可被覆盖 |
2.参考示例及其用法
#基本框架
#FROM COPY 和LABEL用法
#构建镜像时文件都要在同一个目录
[root@docker-node1 ~]# mkdir docker
[root@docker-node1 ~]# cd docker/
[root@docker-node1 docker]# cp /root/anaconda-ks.cfg .
[root@docker-node1 docker]# vim dockerfile
FROM busybox:latest #指定使用的基础镜像
LABEL CREATEUSER=fjw #指定作者信息
COPY anaconda-ks.cfg / #复制当前目录文件到容器指定位置
#开始构建
[root@docker-node1 docker]# docker build -t fjw:v1 .
#查看镜像fjw:1的构建历史
[root@docker-node1 docker]# docker history fjw:v1
IMAGE CREATED CREATED BY SIZE COMMENT
f6596bad8e55 12 seconds ago COPY anaconda-ks.cfg / # buildkit 1.2kB buildkit.dockerfile.v0
<missing> 12 seconds ago LABEL CREATEUSER=fjw 0B buildkit.dockerfile.v0
<missing> 2 years ago BusyBox 1.36.1 (glibc), Debian 12 4.26MB
#验证
[root@docker-node1 docker]# docker run -it --name fjw fjw:v1
/ # ls
anaconda-ks.cfg dev home lib64 root tmp var
bin etc lib proc sys usr
#add与copy区别
[root@docker-node1 docker]# touch fjw1 fjw2 fjw3
[root@docker-node1 docker]# tar zcf fjw.tar.gz fjw1 fjw2 fjw3
#add用法
[root@docker-node1 docker]# vim dockerfile
FROM busybox:latest
LABEL CREATEUSER=fjw
ADD fjw.tar.gz /
[root@docker-node1 docker]# docker build -t fjw:v2 .
#copy用法
[root@docker-node1 docker]# vim dockerfile
FROM busybox:latest
LABEL CREATEUSER=fjw
COPY fjw.tar.gz /
[root@docker-node1 docker]# docker build -t fjw:v3 .
验证


#ENV
[root@docker-node1 docker]# vim dockerfile
FROM busybox:latest
LABEL CREATEUSER=fjw
COPY fjw.tar.gz /
ENV name=fjw
[root@docker-node1 docker]# docker build -t fjw:v4 .
验证

#EXPOSE
[root@docker-node1 docker]# vim dockerfile
FROM busybox:latest
LABEL CREATEUSER=fjw
COPY fjw.tar.gz /
ENV name=fjw
EXPOSE 80 #暴露的端口,构建的容器需要运行业务就需要暴露端口
[root@docker-node1 docker]# docker build -t fjw:v5 .
验证

#WORKDIR
[root@docker-node1 docker]# vim dockerfile
FROM busybox:latest
LABEL CREATEUSER=fjw
COPY fjw.tar.gz /
ENV name=fjw
EXPOSE 80
WORKDIR /etc #运行容器后直接在/etc目录中
[root@docker-node1 docker]# docker build -t fjw:v6 .
验证

#RUN
[root@docker-node1 docker]# vim dockerfile
FROM busybox:latest
LABEL CREATEUSER=fjw
COPY fjw.tar.gz /
ENV name=fjw
EXPOSE 80
WORKDIR /etc
RUN touch haha1 haha2 haha3 #运行容器时在工作目录中创建文件
[root@docker-node1 docker]# docker build -t fjw:v7 .
验证

#CMD
[root@docker-node1 docker]# vim dockerfile
FROM busybox:latest
LABEL CREATEUSER=fjw
COPY fjw.tar.gz /
ENV name=fjw
EXPOSE 80
WORKDIR /etc
RUN touch haha1 haha2 haha3
CMD echo $name
[root@docker-node1 docker]# docker build -t fjw:v8 .
验证

#ENTRYPOINT
[root@docker-node1 docker]# vim dockerfile
FROM busybox:latest
LABEL CREATEUSER=fjw
COPY fjw.tar.gz /
ENV name=fjw
EXPOSE 80
WORKDIR /etc
RUN touch haha1 haha2 haha3
ENTRYPOINT echo $name #与CMD类似但是不能被覆盖
[root@docker-node1 docker]# docker build -t fjw:v9 .
验证

3.镜像构建实例
前提:使用centos镜像构建一个aliyun的镜像仓库,centos源镜像不能安装软件
#构建一个安装nginx的webserver镜像
1.建立构建目录,编写构建文件
[root@docker-node1 ~]# mkdir docker
[root@docker-node1 ~]# cd docker/
[root@docker-node1 docker]# cp /mnt/nginx-1.26.1.tar.gz .
[root@docker-node1 docker]# vim dockerfile
FROM centos.repo:latest
ADD nginx-1.26.1.tar.gz /mnt
RUN yum install gcc make pcre-devel openssl-devel -y
WORKDIR /mnt/nginx-1.26.1
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 && make install
EXPOSE 80
VOLUME ["/usr/local/nginx/html"] #将 Nginx 的网页根目录设为数据卷,方便外部挂载自定义页面
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"] #启动 Nginx 并以非后台模式运行(确保容器不退出)
2.通过dockerfile构建文件生成镜像
[root@docker-node1 docker]# docker build -t webserver:v1 .
3.测试镜像可用性
[root@docker-node1 docker]# docker run -d --name nginx -p 88:80 webserver:v1
测试,访问端口映射的88端口

4.查看容器详情
[root@docker-node1 docker]# docker inspect nginx
4.镜像优化方案
1.缩减镜像层
[root@docker-node1 docker]# vim Dockerfile
FROM centos.repo:latest
ADD nginx-1.26.1.tar.gz /mnt
WORKDIR /mnt/nginx-1.26.1
RUN yum install gcc make pcre-devel openssl-devel -y && 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
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
[root@docker-node1 docker]# docker build -t webserver:v2 .
2.多阶段构建
[root@docker-node1 docker]# vim Dockerfile
FROM centos.repo:latest as built
ADD nginx-1.26.1.tar.gz /mnt
WORKDIR /mnt/nginx-1.26.1
RUN yum install gcc make pcre-devel openssl-devel -y && 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 -rf nginx-1.26.1 && yum clean all
FROM centos.repo:latest
COPY --from=build /usr/local/nginx /usr/local/nginx
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
[root@docker-node1 docker]# docker build -t webserver:v3 .
3.使用最精简镜像
[root@docker-node1 docker]# vim Dockerfile
FROM nginx:1.23 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 /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-debian11
COPY --from=base /opt /
EXPOSE 80 443
ENTRYPOINT ["nginx", "-g", "daemon off;"]
五 搭建docker私有仓库
什么是docker仓库
在搭建docker私有仓库之前,先了解什么是docker的仓库?
Docker 仓库(Docker Registry) 是用于存储和分发 Docker 镜像的集中式存储库。
它就像是一个大型的镜像仓库,开发者可以将自己创建的 Docker 镜像推送到仓库中,也可以从仓库中拉取所需的镜像。
Docker 仓库可以分为公共仓库和私有仓库:
- 公共仓库,如 Docker Hub,任何人都可以访问和使用其中的镜像。许多常用的软件和应用都有在 Docker Hub 上提供的镜像,方便用户直接获取和使用。
- 例如,您想要部署一个 Nginx 服务器,就可以从 Docker Hub 上拉取 Nginx 的镜像。
- 私有仓库则是由组织或个人自己搭建和管理的,用于存储内部使用的、不希望公开的镜像。
- 比如,一家企业为其特定的业务应用创建了定制化的镜像,并将其存储在自己的私有仓库中,以保证安全性和控制访问权限。
通过 Docker 仓库,开发者能够方便地共享和复用镜像,加速应用的开发和部署过程。
docker仓库的工作原理

仓库中的三个角色
index docker索引服务,负责并维护有关用户帐户、镜像的校验以及公共命名空间的信息。
registry docker仓库,是镜像和图表的仓库,它不具有本地数据库以及不提供用户认证,通过Index Auth service的Token的方式进行认证
Registry Client Docker充当registry客户端来维护推送和拉取,以及客户端的授权。
pull原理
镜像拉取分为以下几步:
1.docker客户端向index发送镜像拉去请求并完成与index的认证
2.index发送认证token和镜像位置给dockerclient
3.dockerclient携带token和根据index指引的镜像位置取连接registry
4.Registry会根据client持有的token跟index核实身份合法性
5.index确认此token合法性
6.Registry会根据client的请求传递镜像到客户端
push原理

镜像上传的步骤:
1.client向index发送上传请求并完成用户认证
2.index会发方token给client来证明client的合法性
3.client携带index提供的token连接Registry
4.Registry向index合适token的合法性
5.index证实token的合法性
6.Registry开始接收客户端上传过来的镜像
docker hub
官网:https://hub.docker.com/

Docker Hub 是 Docker 官方提供的一个公共的镜像仓库服务。
它是 Docker 生态系统中最知名和广泛使用的镜像仓库之一,拥有大量的官方和社区贡献的镜像。
以下是 Docker Hub 的一些关键特点和优势:
- 丰富的镜像资源:涵盖了各种常见的操作系统、编程语言运行时、数据库、Web 服务器等众多应用的镜像。
- 例如,您可以轻松找到 Ubuntu、CentOS 等操作系统的镜像,以及 MySQL、Redis 等数据库的镜像。
- 官方支持:提供了由 Docker 官方维护的一些重要镜像,确保其质量和安全性。
- 社区贡献:开发者们可以自由上传和分享他们创建的镜像,促进了知识和资源的共享。
- 版本管理:对于每个镜像,通常都有多个版本可供选择,方便用户根据需求获取特定版本。
- 便于搜索:用户可以通过关键词轻松搜索到所需的镜像。
搭建简单的registry仓库
为什么搭建私有仓库?
纵使docker hub虽然方便,但是还是有限制
- 需要internet连接,速度慢
- 所有人都可以访问
- 由于安全原因企业不允许将镜像放到外网
好消息是docker公司已经将registry开源,我们可以快速构建企业私有仓库
地址: https://docs.docker.com/registry/deploying/
1.下载regisrty镜像
#从公共仓库下载,需要挂梯子
[root@docker-node1 docker]# docker pull registry
#从本地镜像包导入
[root@docker-node1 docker]# docker load -i /mnt/packages/registry.tag.gz
2.运行registry
#--restart=always 在docker开启时同时运行registry这个容器
[root@docker-node1 docker]# docker run -d -p 5000:5000 --restart=always --name repo registry:latest
[root@docker-node1 docker]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e8003291c44e registry:latest "/entrypoint.sh /etc…" 11 minutes ago Up 7 minutes 0.0.0.0:5000->5000/tcp, [::]:5000->5000/tcp repo
3.上传镜像到仓库中
#给上传的镜像打上标签
[root@docker-node1 docker]# docker tag busybox:latest 172.25.254.10:5000/busybox:latest
#docker在上传的过程中默认使用https,但是我们并没有建立https认证需要的认证文件所以会报错
[root@docker-node1 docker]# docker push 172.25.254.10:5000/busybox:latest
The push refers to repository [172.25.254.10:5000/busybox]
Get "https://172.25.254.10:5000/v2/": http: server gave HTTP response to HTTPS client
#配置非加密端口
[root@docker-node1 docker]# vim /etc/docker/daemon.json
[root@docker-node1 docker]# cat /etc/docker/daemon.json
{
"insecure-registries" : ["http://172.25.254.10:5000"]
}
[root@docker-node1 docker]# systemctl restart docker
[root@docker-node1 docker]# docker push 172.25.254.10:5000/busybox:latest
The push refers to repository [172.25.254.10:5000/busybox]
d51af96cf93e: Pushed
latest: digest: sha256:28e01ab32c9dbcbaae96cf0d5b472f22e231d9e603811857b295e61197e40a9b size: 527
#查看镜像上传
[root@docker-node1 docker]# curl 172.25.254.10:5000/v2/_catalog
{"repositories":["busybox"]}
搭建加密仓库
#生成公钥与证书
[root@docker-node1 docker]# openssl req -newkey rsa:4096 \
> -nodes -sha256 -keyout /data/certs/fy.org.key \
> -addext "subjectAltName = DNS:reg.fy.org" \ #使用域名作为仓库名称
> -x509 -days 365 -out /data/certs/fy.org.crt
Country Name (2 letter code) [XX]:cn
State or Province Name (full name) []:GD
Locality Name (eg, city) [Default City]:gz
Organization Name (eg, company) [Default Company Ltd]:fy.org
Organizational Unit Name (eg, section) []:docker
Common Name (eg, your name or your server's hostname) []:reg.fy.org #要与-addext的域名相同,否则docker验证过不去
Email Address []:11
#启动存放镜像的仓库容器
[root@docker-node1 docker]# docker run -d -p 443:443 --restart=always --name repo \
> -v /opt/registry:/var/lib/registry \ #将主机的 /opt/registry 目录挂载到容器内的仓库数据目录(存储镜像数据),实现数据持久化
> -v /data/certs:/certs \
> -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
> -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/fy.org.crt \
> -e REGISTRY_HTTP_TLS_KEY=/certs/fy.org.key registry
#查看运行情况
[root@docker-node1 docker]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e00abc56cc13 registry "/entrypoint.sh /etc…" 9 seconds ago Up 8 seconds 0.0.0.0:443->443/tcp, [::]:443->443/tcp, 5000/tcp repo
#如果有问题就查看容器日志
[root@docker-node1 docker]# docker logs repo
#此时如果不生成证书目录,直接推送或拉取镜像会报错
[root@docker-node1 docker]# docker tag busybox:latest reg.fy.org/busybox:latest
[root@docker-node1 docker]# docker push reg.fy.org/busybox:latest
Error response from daemon: Get "https://reg.timinglee.org/v2/": tls: failed to
verify certificate: x509: certificate signed by unknown authority
#服务端作为客户端使用时,直接在本机拷贝就行
[root@docker-node1 docker]# mkdir /etc/docker/certs.d/reg.fy.org/ -p
[root@docker-node1 docker]# cp /data/certs/fy.org.crt /etc/docker/certs.d/reg.fy.org/ca.crt
[root@docker-node1 docker]# systemctl restart docker #重启docker读取生效
[root@docker-node1 docker]# docker tag busybox:latest reg.fy.org/busybox:latest
[root@docker-node1 docker]# docker push reg.fy.org/busybox:latest
[root@docker-node1 docker]# curl -k https://reg.fy.org/v2/_catalog
{"repositories":["busybox"]}
[root@docker-node1 docker]# cat /etc/hosts
......
172.25.254.10 reg.fy.org
#使用另一个客户端测试
#先添加镜像仓库的本地域名解析
[root@docker-node2 docker]# cat /etc/hosts
......
172.25.254.10 reg.fy.org
#为客户端建立证书
[root@docker-node1 reg.fy.org]# scp -r /etc/docker/certs.d/ root@172.25.254.20:/etc/docker/
#查看镜像仓库里的镜像
[root@docker-node2 ~]# curl -k https://reg.fy.org/v2/_catalog
{"repositories":["busybox","nginx"]}
#拉取镜像到本地
[root@docker-node2 ~]# docker pull reg.fy.org/busybox #不加版本默认是latest
[root@docker-node2 ~]# docker pull reg.fy.org/nginx
[root@docker-node2 ~]# docker imges
REPOSITORY TAG IMAGE ID CREATED SIZE
reg.fy.org/nginx latest 5ef79149e0ec 11 months ago 188MB
reg.fy.org/busybox latest 65ad0d468eb1 2 years ago 4.26MB
仓库建登录认证
1.安装建立认证文件的工具包与创建认证用户
#安装工具包
[root@docker-node1 ~]# dnf install httpd-tools -y
#建立认证文件并创建用户
[root@docker-node1 ~]# mkdir /data/auth
[root@docker-node1 ~]# htpasswd -Bc /data/auth/htpasswd admin #-B 强制使用最安全加密方式
New password:
Re-type new password:
Adding password for user admin
[root@docker-node1 ~]# htpasswd -B /data/auth/htpasswd fjw #创建第二个用户时不用+c,不然会覆盖
New password:
Re-type new password:
Adding password for user fjw
[root@docker-node1 ~]# cat /data/auth/htpasswd
admin:$2y$05$lwl8H1OPdMW2k54k0jPSi.BQnbj9JlbNFX7KH45HwMqbKsq5KJsha
fjw:$2y$05$BTfy0UcXi5oszxiH8VZxmug2/PTq7LIb5m.DnOlX.lztW8irYmTly
2.运行仓库容器,并添加认证到仓库容器中
[root@docker ~]# docker run -d -p 443:443 --restart=always --name registry \
> --name registry -v /opt/registry:/var/lib/registry \
> -v /data/certs:/certs \
> -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
> -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/fy.org.crt \
> -e REGISTRY_HTTP_TLS_KEY=/certs/fy.org.key \
> -v /data/auth:/auth \
> -e "REGISTRY_AUTH=htpasswd" \
> -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
> -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
> registry
[root@docker-node1 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9e4fb308ed91 registry "/entrypoint.sh /etc…" 44 seconds ago Restarting (1) 14 seconds ago repo
3.访问测试
#不加认证时,会禁止访问
[root@docker-node2 ~]# curl -k https://reg.fy.org/v2/_catalog
{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":[{"Type":"registry","Class":"","Name":"catalog","Action":"*"}]}]}
#-u添加认证用户与密码
[root@docker-node2 ~]# curl -k https://reg.fy.org/v2/_catalog -uadmin:fjw
{"repositories":["busybox","nginx"]} #做了容器挂载持久化
4.登录测试
#没有登录镜像仓库时直接拉取镜像
[root@docker-node2 ~]# docker pull reg.fy.org/nginx
Using default tag: latest
Error response from daemon: Head "https://reg.fy.org/v2/nginx/manifests/latest": no basic auth credentials
#使用认证用户登录镜像仓库
[root@docker-node2 ~]# docker login -uadmin -pfjw reg.fy.org
Login Succeeded
#登陆后拉取镜像到本地
[root@docker-node2 ~]# docker pull reg.fy.org/nginx
Using default tag: latest
latest: Pulling from nginx
Digest: sha256:127262f8c4c716652d0e7863bba3b8c45bc9214a57d13786c854272102f7c945
Status: Image is up to date for reg.fy.org/nginx:latest
reg.fy.org/nginx:latest
[root@docker-node2 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
reg.fy.org/nginx latest 5ef79149e0ec 11 months ago 188MB
拓展
#查看认证信息
#在哪个用户登录就在哪个用户的家目录里的隐藏文件
[root@docker-node2 ~]# ls -a
[root@docker-node2 ~]# cd .docker/
[root@docker-node2 .docker]# cat config.json
{
"auths": {
"reg.fy.org": {
"auth": "YWRtaW46Zmp3"
}
}
#退出镜像仓库,查看认证信息
[root@docker-node2 .docker]# docker logout reg.fy.org
Removing login credentials for reg.fy.org
[root@docker-node2 .docker]# cat config.json
{
"auths": {}
}
#补充
[root@docker-node2 ~]# vim /etc/docker/daemon.json
{
"registry-mirrors": {"https://reg.fy.org"}
}
[root@docker-node2 ~]# systemctl restart docker
[root@docker-node2 ~]# docker info
......
Registry Mirrors:
https://reg.fy.org/
......
搭建企业级私有仓库
1.部署harbor
[root@docker-node1 ~]# tar zxf harbor-offline-installer-v2.5.4.tgz
[root@docker-node1 ~]# cd harbor/
#拷贝模板,生成harbor配置文件
[root@docker-node1 harbor]# cp harbor.yml.tmpl harbor.yml
#编辑配置文件
[root@docker-node1 harbor]# vim harbor.yml

#安装habor
[root@docker-node1 harbor]# ./install.sh --help
--with-notary #扫描容器镜像,对容器镜像进行签名,确保来源可靠
--with-trivy #对仓库镜像进行扫描,及时发现漏洞,确保容器应用安全
--with-chartmuseum #存储和共享Helm Charts的服务器,助于管理k8s应用
[root@docker-node1 harbor]# ./install.sh --with-chartmuseum
#管理harbor的容器
[root@docker-node1 harbor]# docker compose stop #停止harbor的容器
[root@docker-node1 harbor]# docker compose start #开启harbor的容器
[root@docker-node1 harbor]# docker compose up -d #部署/重建并启动
#查看导入的镜像与开启的容器
[root@docker-node1 harbor]# docker images
[root@docker-node1 harbor]# docker ps
补充
#由于docker版本更新,habor安装时会出现版本报错

#解决方法
[root@docker-node1 harbor]# docker compose stop
[root@docker-node1 harbor]# vim docker-compose.yml
#version: '2.3'
[root@docker-node1 harbor]# docker compose start
2.管理仓库
1.登录,访问habor主机默认被端口映射到80

2.建立仓库项目
#不建立的话默认上传的镜像会存放在library中

3.上传镜像
#登录镜像仓库
[root@docker-node1 harbor]# docker login -uadmin -pfjw reg.fy.org
#上传与标签格式:仓库名称/目录/镜像名称
[root@docker-node1 harbor]# docker tag nginx:latest reg.fy.org/fjwyyy/nginx:latest
[root@docker-node1 harbor]# docker push reg.fy.org/fjwyyy/nginx:latest
#查看上传的镜像

4.使用客户端进行拉取仓库镜像到本地
#要有本地解析,还要有证书
#登录仓库
[root@docker-node2 ~]# docker login -uadmin reg.fy.org
Password:
Login Succeeded
#拉取镜像到本地
#格式为目录/镜像名称 默认版本为latest不指定的话
[root@docker-node2 ~]# docker pull fjwyyy/nginx
#上传到默认library目录的镜像,在拉取时可以不指定目录
[root@docker-node2 ~]# docker pull busybox
更多推荐
所有评论(0)