乐于分享
好东西不私藏

docker怎么学,一篇文档教会你

docker怎么学,一篇文档教会你

之前我录个docker的零基础教程,是23年5月份的时候

那个时候docker换个国内源就可以正常拉取镜像了

但是24年之后,受到众所周知的原因,所有的国内docker源都不行了

所以大大增加了入门难度

再加上内容有点浅显了,本课程再加点内容,并且前期尽量讲的通俗易懂

docker能干啥

试想一个场景,你开在windows上开发的一个web项目

好巧不巧,你是用python开发的,然后部署到服务器的时候,先是费劲的安装mysql,redis,nginx这些中间件,然后跑python项目,发现死活跑不起来,要不就提示少包,要不就提示函数不存在,咋回事呢?

使用docker之后,以后安装mysql、redis、es、nginx这些中间件这些就只需要一条命令即可

并且以后做的项目,项目部署也只需要一两条命令即可,大大方便了开发安装、部署流程

能看到这个文档的,我相信大家应该很焦虑啊,网上说啥的都有,什么docker不行了,现在都是k8s了,podman未来要取代docker等等

我反正就一句话,该学学,该用用,真的淘汰了就去拥抱新变化

我之前也学了jQuery,还用django写了前后端不分离的网站

但是也不妨碍我现在又学了go,用前后端分离的技术写网站

什么是docker

docker是一个用Go语言实现的开源项目,可以让我们方便的创建和使用容器,docker将程序以及程序所有的依赖都打包到docker container,这样你的程序可以在任何环境都会有一致的表现

我一直觉得没有docker,各个中间件的安装将会变得非常困难,比如安装mysql、es、nginx这些,因为不同的系统安装流程还不太一样

现在有了docker之后,只需要写个命令,只要我能跑起来,你运行这个命令也就能跑起来,和操作系统没关系

docker安装

本课程统一都使用linux/centos7系统安装docker,并且在此系统上进行docker的使用

# 删除之前的docker残留yum -y remove docker* yum install -y yum-utils yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo  yum install docker-ce docker-ce-cli containerd.io -y # 启动dockersystemctl start docker # 开机启动systemctl enable docker 

不太建议在windows上使用docker,一是windows上使用docker性能不太好,二是有细微的差异(比如host网络),三是实际部署的系统都是linux系统

yum用不了的,记得换源

cp /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo yum clean all yum makecache 

docker设置代理

从2024年开始,中国境内就不能在通过docker换国内源下载镜像了

这一点确实劝退了很多人

如果不会魔法的同学,可以使用腾讯云的服务器,腾讯云有docker私有源,可以下载镜像

也可以买一个境外、国外的服务器,也可以直接拉取docker镜像

真要随心所欲的拉取镜像,最好的方法还是学会魔法,以及配置docker代理

当然,本课程只能教你如何配置docker代理

创建 /etc/systemd/system/docker.service.d/http-proxy.conf 配置文件 [Service]Environment="HTTP_PROXY=http://192.168.80.1:7890"Environment="HTTPS_PROXY=http://192.168.80.1:7890"然后重新加载配置并重启服务: systemctl daemon-reload systemctl restart docker 然后检查加载的配置: systemctl show docker --property Environment 

记得代理软件要开启内网访问

docker快速使用

大家是怎么安装mysql的呢?

原生安装?

翻遍官网找安装文件,又要配置密码,也要配置访问策略,太麻烦

使用docker,直接一条命令

docker run -itd -p 3306:3306 --name=mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7 

然后用你的mysql客户端,就可以连上你的mysql了,爽死

好了,我相信docker应该勾起了你的学习兴趣了,那么课程正式开始!

如果访问不了,大概率是端口没开

firewall-cmd --list-ports   firewall-cmd --zone=public --add-port=80/tcp --permanent   firewall-cmd --reload   

docker镜像

学习docker,从镜像开始

上面我提到的mysql、redis等,在dockerhub上就会有大佬或者官方把这些中间件制作成docker镜像

我们只需要使用docker pull 镜像名 就可以下载到我们本地了

镜像的基本操作

# 拉取镜像docker pull image_name:tag # 不写tag,默认是latest# 检索镜像docker search image_name:tag # 列表docker images # 删除镜像docker rmi image_id 

docker容器

可以理解为一个非常精简的操作系统

在这个操作系统上,只部署了你需要的服务,也就是你对应的镜像

比如nginx的镜像,它运行的容器,就表示这个操作系统里面只有nginx这个软件服务

比如mysql的镜像,它运行的容器,就表示这个操作系统里面只有mysql这个软件服务

容器是 Docker 最核心的概念,本质是基于镜像运行的隔离进程—— 它复用宿主机内核,通过 Namespace、Cgroups 等技术实现资源隔离(网络、文件系统、进程)和限制(CPU、内存),比虚拟机更轻量、启动更快。

容器列表

# 查看正在运行中的容器docker ps # 查看所有容器docker ps -a # 只获取容器iddocker ps -a -q # 指定输出的内容docker ps -a --format "table {{.ID}}\t{{.Names}}"

运行容器

docker run [选项] <镜像名:标签> [容器启动参数]

选项

  1. --name
     表示为启动的容器起个名字,这个名字在宿主机上唯一
  2. -t
      为docker分配一个伪终端并绑定到容器的标准输入上
  3. -i
      是让容器的标准输入保持打开状态
  4. -v
     目录映射,实现数据的持久化,冒号前面表示宿主机的目录,后面是容器内目录。目录不存在会自动生成。
  5. -p
      端口映射,宿主机端口:容器端口
  6. -e
     表示要设置环境变量
  7. -d
     表示要以分离模式(也就是后台模式)启动容器,这样执行后会返回容器ID,不会进入交互界面。如果想要进入交互界面需要-i 和-t参数。
  8. --restart
     表示容器重启策略
  9. --privileged
     表示是否使用特权模式,设置–privileged=true提升系统执行权限。设置为true后,容器内的root用户才是真正的root权限,否则只是一个普通用户。

容器运行

以mysql为例

# 后台运行 并且 暴露端口 -p 宿主机端口:容器内端口docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=123456 -p 3307:3306 mysql:5.7 # 传递环境变量 配置数据库名docker run -d --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=blog mysql:5.7 # 数据挂载 重启mysql,数据也不会丢失 -v 宿主机路径:容器内路径docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 -v ./mysql_data:/var/lib/mysql mysql:5.7 # 限制 1G 内存、1 个 CPU 核心,超出内存时容器自动终止docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 --memory 1G --cpus 1 mysql:5.7 # 容器重启策略:always(总是重启,除非手动停止)docker run -d --name  mysql -e MYSQL_ROOT_PASSWORD=123456 --restart always mysql:5.7 #on-failure[:max-retries]:仅在容器退出码非 0 时重启(可指定最大重试次数);#always:总是重启(包括手动停止后重启 Docker 服务时);#unless-stopped:除非手动停止,否则一直重启。

容器操作

# 停止容器docker stop docker_id # 启动容器docker start docker_id # 重启容器docker restart docker_id # 删除没有运行的容器docker rm docker_id # 删除运行中的容器docker rm -f docker_id  # 停止所有容器docker stop $(docker ps -a -q)# 删除所有容器docker rm -f $(docker ps -a -q)

查看日志

# 查看这个容器的全部日志docker logs <容器名称> # 持续查看日志docker logs -f <容器名称> # 持续查看前10条日志docker logs -f -n 10 <容器名称> # 持续查看前10条日志 老版本dockerdocker logs -f --tail=10 <容器名称> 

进入容器

容器本质是隔离的进程,进入容器 本质是在该隔离进程的 Namespace(命名空间)中启动一个新的终端进程(如 shbash),从而可以查看容器内文件、执行命令、调试 Go 程序(如查看进程、日志、修改配置)。

关键前提:只有运行中的容器才能进入

docker exec -it <容器名/容器ID> <容器内执行的命令> 

端口映射

Docker 容器默认有独立的网络命名空间(隔离的网络环境),容器内的 mysql 服务监听的端口(如 3306)仅能在容器内访问。端口映射通过 Docker 的 iptables 规则,将「宿主机的端口」与「容器内的端口」建立映射关系,外部请求访问宿主机端口时,会被转发到容器内对应的端口,从而实现外部访问mysql 服务。

类比:容器是一个 “独立房间”,mysql服务在房间内的3306 端口提供服务;端口映射相当于在房间门上贴了一个 “门牌号(宿主机端口 3306)”,外部访客按门牌号敲门,会被引导到房间内的 3306 端口。

# 宿主机 3306 端口 → 容器 3306 端口(外部通过 http://宿主机IP:3306 访问)docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=123456 -p 3307:3306 mysql:5.7 # 宿主机随机端口 → 容器 3306 端口docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=123456 -p 3306 mysql:5.7 # 仅 192.168.80.185 这个网卡的 3306 端口映射到容器 3306docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=123456 -p 192.168.80.185.100:3306:3306 mysql:5.7 # 映射 多个端口docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=123456 -p 3307:3306 -p 3306:3306 mysql:5.7 

容器内的 服务必须监听 0.0.0.0(而非 127.0.0.1),否则仅容器内可访问,外部无法通过端口映射访问(核心避坑点)。

比如 go的web服务

// 错误:仅容器内可访问http.ListenAndServe("127.0.0.1:8080"nil// 正确:外部可通过端口映射访问http.ListenAndServe(":8080"nil)  // 等价于 0.0.0.0:8080

目录映射

容器的文件系统是 “临时层”—— 基于镜像的只读层创建可写层,容器删除后,可写层的文件(如日志、配置修改、数据库数据)会丢失。目录映射(也叫 “挂载”)通过将「宿主机的目录 / 文件」与「容器内的目录 / 文件」建立关联,实现:

  • 数据持久化:程序写入的日志、数据存储到宿主机,容器删除后数据不丢失;
  • 文件共享:宿主机修改配置文件,容器内实时生效(无需重启容器);
  • 避免镜像膨胀:无需将大文件(如日志、数据库)打包到镜像中。

Docker 支持两种目录映射方式:绑定挂载(Bind Mount) 和 数据卷(Volume),Go 场景中前者用于配置文件 / 日志,后者用于重要数据(如数据库)。

绑定挂载

直接将宿主机的自定义目录 / 文件挂载到容器,适合需要手动修改、查看的场景(如配置文件、日志目录)。

docker run -v <宿主机路径>:<容器内路径>[:权限] <镜像名> # ro:只读(容器内只能读取,不能修改宿主机文件);# rw:读写(默认,容器内可修改宿主机文件)。
# 宿主机 ./mysql_data 目录 → 容器 /var/lib/mysql 目录(读写权限)docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=123456 -v ./mysql_data:/var/lib/mysql mysql:5.7 # 目录映射之后,删除容器再执行运行命令,数据依然还在# 宿主机 ./xxx.txt 文件 → 容器 /etc/mysql/xxx.txt 文件(只读权限,防止容器修改)docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=123456  -v ./xxx.txt:/xxx.txt:ro mysql:5.7 

要注意,直接用vi、vim修改文件,很可能是不会同步的,因为vi编辑是创建一个新文件然后把老文件删掉,再把新文件替换的方式,会打破docker的同步机制

数据卷(Volume)

Docker 管理的持久化存储

数据卷是 Docker 专门创建的持久化目录(存储在宿主机 /var/lib/docker/volumes/ 下),由 Docker 自动管理,无需手动维护宿主机路径,适合存储重要数据

核心优势

  • 跨平台兼容性好(Docker 统一管理路径,不受宿主机目录结构影响);
  • 支持权限控制、数据卷备份 / 恢复;
  • 可在多个容器间共享数据(如多个服务共享同一个数据卷)。
# 创建名为 mysql_data 的数据卷docker volume create mysql_data # 数据卷 mysql_data → 容器 /var/lib/mysql 目录docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 -v mysql_data:/var/lib/mysql mysql:5.7 # 查看所有数据卷docker volume ls # 查看数据卷详情(如存储路径)docker volume inspect mysql_data # 删除数据卷(需先解绑所有容器)docker volume rm mysql_data # 清理所有未使用的卷docker volume prune 

容器常见问题

容器启动就报错?

  1. 先docker logs看日志,如果日志有错误输出,基本上就知道怎么去解决
  2. 没有日志?docker run … sh 重新跑这个容器,肯定能跑起来,跑起来进容器手动执行本来的启动命令,看看是什么反应

容器启动后,容器里面挂载目录下的原有文件消失

宿主机挂载目录为空,会覆盖容器内目录的原有文件(Docker 挂载规则:宿主机目录优先级高于容器内目录);

宿主机挂载的文件变成了目录?

Docker 挂载的「源路径」如果在宿主机上不存在,Docker 会默认创建一个「目录」而非「文件」—— 哪怕你在容器内的目标路径写的是文件,也会被这个新建的目录覆盖,最终容器内看到的就是目录,而非预期的文件。

镜像构建

上面的docker镜像和docker容器学完之后,可以覆盖你50%的docker应用场景了

针对一些复杂的操作,比如部署go项目、python这些自己的项目

又或者在一些基础镜像的基础上,安装一些软件

那就得写Dockerfile文件了

先看部署go项目的dockerfile示例

# 注释:指定基础镜像(必填,所有指令的起点)FROMgolang:alpineASbuilder# 设置环境变量ENV CGO_ENABLED 0ENV GOPROXY https://goproxy.cn,directRUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories# 设置工作目录WORKDIR/build# 复制文件ADD go.mod .COPY go.sum .ADD main.go .# 执行命令RUN go build -o mainFROMalpineWORKDIR/app# 维护者信息LABEL maintainer="fengfeng@xx.com"LABEL version="1.0"LABEL description="A demo Docker image for go app"# 元数据可通过 docker inspect <镜像名>  便于镜像管理# 多阶段构建COPY --from=builder /build/main /appRUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositoriesRUN apk add bash# 容器启动时执行的命令(必填,仅最后一个生效)CMD ["./main"]# 暴露端口(仅声明,不实际映射,用于文档说明)EXPOSE8080

构建命令

# 完整命令docker build -f Dockerfile -t demo-app:v1.0  . # 可省略-fdocker build  -t demo-app:v1.0  . 

构建上下文

docker build 最后一个参数(如 ./home/user/project)指定的路径,就是「构建上下文」。Docker 客户端会将该路径下的所有文件 / 目录打包,发送给 Docker 守护进程(daemon),供 Dockerfile 中的 COPY/ADD 指令读取文件。

需要额外了解的

COPY和ADD

本地文件 / 目录复制到镜像的指定路径,核心区别:ADD 支持自动解压压缩包、下载 URL 文件(不推荐,建议用 RUN wget 替代)。

# 复制本地 项目的所有文件到 到镜像的 /app 目录COPY .  .# ADD 自动解压本地压缩包到镜像(如 tar.gz、zip)ADD .  /app/

RUN、CMD和ENTRYPOINT

run:在镜像构建过程中执行命令(如安装依赖、解压文件、创建目录),执行结果会被固化到镜像的分层中。

两种格式

# Shell 格式:安装 nginx(合并命令减少镜像分层)RUN apt update && apt install -y nginx && rm -rf /var/lib/apt/lists/*# Exec 格式:创建目录(无 Shell 环境,不支持变量替换)RUN["mkdir""-p""/app/logs"]

cmd:默认启动命令,可被 docker run 后面的参数覆盖;

ENTRYPOINT:入口命令,docker run 后面的参数会作为其参数追加,不可覆盖(除非用 --entrypoint 参数强制替换)。

# ENTRYPOINT:固定启动命令ENTRYPOINT ["./main"]# CMD:默认启动参数# 这里默认指定 --env=dev 和 --port=8080,运行时可替换CMD ["--env""dev""--port""8080"]

docker网络

Docker 网络是实现容器间、容器与外部(宿主机 / 互联网)通信的核心组件,其本质是通过 Linux 网络命名空间(Network Namespace) 实现容器网络隔离,再通过桥接、路由、端口映射等技术打通通信通道。

安装 Docker 后,会自动创建 3 个默认网络

docker network ls NETWORK ID     NAME      DRIVER    SCOPE abc123xyz     bridge    bridge    local  # 默认桥接网络def456uvw     host      host      local  # 主机模式网络ghi789rst     none      null      local  # 无网络模式

桥接网络

容器启动时,Docker 自动分配:

  • 独立 IP(如 172.17.0.2、172.17.0.3,子网默认 172.17.0.0/16);
  • 网关(宿主机 docker0 网桥 IP,如 172.17.0.1);

容器间通过 IP 通信,外部通过端口映射(-p)访问容器内的服务。

局限性:

  • 默认桥接网络不支持 容器名解析(只能通过 IP 通信);
  • 所有默认桥接模式的容器在同一网段,隔离性较差(适合单服务,不适合多服务集群)。

自建桥接网络

手动创建的桥接网络,相比默认 bridge 有 2 个核心优势:

  • 支持 容器名解析(容器间可通过容器名作为主机名通信,无需记 IP);
  • 网络隔离(不同自定义网络的容器无法通信,安全性更高)。
# 创建名为 go-microservice 的自定义桥接网络docker network create go-microservice # 启动依赖容器(Redis)并加入网络docker run -d --name redis --network go-microservice redis:alpine # 另一个容器也加入这个网络docker run -d --name go-server --network go-microservice -p 8081:8080 go-demo:1.0 # 然后在这个容器里面,就可以直接容器名访问对应的ip

自定义容器网络网段和容器ip

# 创建网段为 172.20.0.0/16、网关为 172.20.0.1 的自定义网络docker network create --subnet 172.20.0.0/16 --gateway 172.20.0.1 go-fixed-ip-network # 查看网络详情(确认网段和网关)docker network inspect go-fixed-ip-network # 指定固定 IP 172.18.0.10(需在自定义网络子网内)docker run -d --name go-server --network go-fixed-ip-network --ip 172.20.0.10 go-demo:1.0 

主机模式

容器共享宿主机的网络命名空间,意味着:

  • 容器没有独立 IP,直接使用宿主机的 IP;
  • 容器内的端口直接暴露在宿主机上(无需 "-p" 端口映射);
  • 容器内的网络配置(如路由、DNS)与宿主机完全一致。

局限性

  • 端口冲突风险:容器内端口与宿主机 / 其他容器端口冲突会导致启动失败;
  • 安全性较低:容器直接暴露在宿主机网络,无隔离性;
  • 跨平台不兼容:Windows/Mac 系统上 host 模式有兼容性限制(推荐仅在 Linux 上使用)。
# 启动 Go 容器,使用 host 模式,监听宿主机 8080 端口docker run -d --name go-server --net=host go-demo:1.0 --port 8080

docker compose

Docker Compose 是 Docker 官方提供的多容器应用编排工具,核心作用是通过一个统一的配置文件(默认 docker-compose.yml)定义、管理多个关联的 Docker 容器,实现「一键启动 / 停止 / 销毁」整个应用集群,解决了手动逐个操作容器(如网络配置、依赖顺序、端口映射)的繁琐问题。

当你的应用依赖多个服务时(比如:Web 服务 + 数据库 + 缓存 + 消息队列),手动操作会面临以下痛点:

  1. 需逐个运行 docker run 命令,参数冗长(端口、网络、数据卷、环境变量等);
  2. 需手动维护容器间的网络连通(如让 Web 容器访问 DB 容器);
  3. 容器启动顺序有依赖(必须先启动 DB,再启动 Web);
  4. 服务扩容、重启、日志查看需逐个操作。

而 Docker Compose 可以:

  • 用一个 YAML 文件声明所有服务配置;
  • 一键启动 / 停止所有服务(docker-compose up/down);
  • 自动创建独立网络,让容器间通过服务名互通;
  • 维护容器依赖关系、数据卷持久化、环境变量隔离;
  • 统一查看所有服务日志、扩容服务实例。

基本结构

# 版本声明(推荐 v3,兼容 Docker 17.06+)version'3'# 定义所有服务(核心模块,每个服务对应一个容器)services服务1名称# 镜像(必填):来自 Docker Hub 或自定义镜像image镜像名:标签# 容器名称(可选,默认自动生成)container_name容器名# 端口映射(可选):主机端口:容器端口ports      - "主机端口1:容器端口1"      - "主机端口2:容器端口2"# 环境变量(可选):两种写法environment      - 键=值 # 直接写      - 键2=值2env_file:  # 从文件读取(优先级低于 environment)      - .env# 数据卷(可选):持久化数据或挂载主机目录volumes      - 主机目录:容器目录 # 绑定挂载      - 数据卷名称:容器目录 # 命名数据卷# 依赖服务(可选):启动顺序(先启动依赖的服务)depends_on      - 服务2名称      - 服务3名称# 网络(可选):指定服务加入的网络networks      - 自定义网络名# 重启策略(可选):容器退出后的重启规则restartalways # 可选:no/on-failure/unless-stopped# 定义网络(可选,默认会创建一个默认网络)networks自定义网络名driverbridge # 网络驱动(默认 bridge,支持 overlay 等)# 定义数据卷(可选,用于持久化服务数据)volumes数据卷名称driverlocal # 数据卷驱动(默认 local)

示例

# 版本声明(推荐 v3,兼容 Docker 17.06+)version'3'# 定义所有服务(核心模块,每个服务对应一个容器)servicesweb# 镜像(必填):来自 Docker Hub 或自定义镜像imageweb:v1# 容器名称(可选,默认自动生成)#    container_name: 容器名# 端口映射(可选):主机端口:容器端口ports      - "8081:8080"# 环境变量(可选):两种写法environment      - xxx=dev # 直接写# 网络(可选):指定服务加入的网络networks      - xx_net# 重启策略(可选):容器退出后的重启规则restartalways # 可选:no/on-failure/unless-stoppedweb1imageweb:v1ports      - "8082:8080"networks      - xx_netrestartalways# 定义网络(可选,默认会创建一个默认网络)networksxx_netdriverbridge # 网络驱动(默认 bridge,支持 overlay 等)

常用命令

# 后台启动所有服务docker compose up -d # 查看 web 服务的实时日志docker compose logs -f web # 进入 db 服务容器(如 MySQL)docker compose exec db bash # 停止所有服务(保留容器和数据卷)docker compose stop # 停止并删除所有服务、网络、容器(保留数据卷)docker compose down # 停止并删除所有(包括数据卷)docker compose down -v 

实战:go+mysql部署

servicesblogimageweb:v3networks      - blogrestartalwaysvolumes      - ./settings.yaml:/app/settings.yamldepends_on      - mysqlmysqlimagemysql:5.7environment      - MYSQL_ROOT_PASSWORD=123456      - MYSQL_DATABASE=blogvolumes      - ./mysql_data:/var/lib/mysqlnetworks      - blogrestartalways# 定义网络(可选,默认会创建一个默认网络)networksblogdriverbridge # 网络驱动(默认 bridge,支持 overlay 等)

go语言对接docker api

有些情况下,需要通过代码实现对容器的操作

比如获取容器列表,获取镜像列表,创建容器,删除容器

packagemainimport ( "context""fmt""github.com/docker/docker/api/types/container""github.com/docker/docker/api/types/image""github.com/docker/go-connections/nat""log""github.com/docker/docker/client"varcli*client.Clientfuncinit() { // 初始化 Docker 客户端(使用默认端点)// 如需自定义端点(如远程 Docker 服务),可通过 client.WithHost("tcp://192.168.1.100:2375") 指定_clierr:=client.NewClientWithOpts(client.FromEnvclient.WithAPIVersionNegotiation()) iferr!=nil { log.Fatalf("创建 Docker 客户端失败:%v"err  } //defer cli.Close() // 退出时关闭客户端连接fmt.Println("Docker 客户端连接成功!"cli = _clifuncimageList() { list_:=cli.ImageList(context.Background(), image.ListOptions{}) for_summary:=rangelist { fmt.Printf("%s %s\n"summary.ID[7:19], summary.RepoTags  } funccontainerList() { list_:=cli.ContainerList(context.Background(), container.ListOptions{}) for_summary:=rangelist { fmt.Println(summary.ID[7:19], summary.Namessummary.Statesummary.Image  } //func (cli *Client) ContainerCreate(//  ctx context.Context,          // 上下文(控制超时、取消等)//  config *container.Config,      // 容器核心配置(对应之前你问的 Config 结构体)//  hostConfig *container.HostConfig,  // 主机资源配置(与宿主机交互相关)//  networkingConfig *network.NetworkingConfig,  // 网络配置(容器网络栈、端口映射等)//  platform *ocispec.Platform,    // 目标平台(跨架构场景用,如 arm64/amd64)//  containerName string           // 容器名称(可选,如不指定则自动生成)//) (container.CreateResponse, error)funccontainerCreate() { responseerr:=cli.ContainerCreatecontext.Background(), &container.ConfigAttachStdin:  trueAttachStdouttrueOpenStdin:    trueStdinOnce:    trueImage:        "alpine:latest"Cmd:          []string{"sh"},     }, &container.HostConfigPortBindingsnat.PortMap"80": []nat.PortBinding          { HostIP:   "0.0.0.0"HostPort"80"          },         },       },     }, nilnil"alpine"  ) iferr!=nil { fmt.Println("创建容器失败"errreturn  } fmt.Println("容器创建成功"response.IDerr = cli.ContainerStart(context.Background(), response.IDcontainer.StartOptions{}) iferr!=nil { fmt.Println("容器启动失败"errreturn  } fmt.Println("容器启动成功"funcmain() { containerCreate() 

docker自建仓库

在内网环境下,如果很多服务器都需要下载镜像,每个都去配置docker代理会不太方便

所以更多时候可以在一个服务器集中存镜像,在那个服务器上运行docker registry服务,创建一个docker镜像仓库

其他服务器就可以直接拉取这个机器的镜像

docker pull registry

修改配置文件

Docker 官方默认要求镜像仓库(Registry)必须使用 HTTPS 协议 通信(保证传输加密和身份验证)。但实际场景中,很多企业 / 个人会搭建 私有镜像仓库(比如用 Docker 官方的 registry 镜像搭建),这类私有仓库可能因成本 / 环境限制,只开启 HTTP 协议(未配置 HTTPS 证书)。

insecure-registries(中文:“不安全的仓库”):告诉 Docker 「以下仓库是可信的,允许用 HTTP 协议通信,无需验证 HTTPS 证书」。

vim /etc/docker/daemon.json {"insecure-registries"["192.168.80.185:5000"]}systemctl restart docker 

运行registry服务

docker run -itd -v /data/registry:/var/lib/registry -p 5000:5000 --restart=always --name registry registry:latest 

上传镜像

# 给镜像打tagdocker tag alpine:latest 192.168.80.185:5000/alpine:latest # 上传到私有仓库docker push 192.168.80.185:5000/alpine:latest 

拉取镜像

要配置insecure-registries

docker pull 192.168.80.185:5000/alpine