🐳 Docker 远程部署(Server + Client)

🗺️ 环境说明

主机IP地址角色
🖥️ docker_server192.168.108.30Docker Engine 服务端
💻 docker_client192.168.108.31Docker Client 客户端

📝 架构:Client 通过 -H 远程连接 Server 的 Docker Daemon,本地不运行 docker daemon


1️⃣ Docker Server 配置(192.168.108.30)

📦 安装依赖

[root@docker_server ~]# yum install -y yum-utils device-mapper-persistent-data
# ✅ yum-utils-4.0.21-25.el8.noarch 安装完成

📥 添加 Docker CE 源(阿里云镜像)

[root@docker_server ~]# yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# Adding repo from: https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

⚙️ 安装 Docker Engine

[root@docker_server ~]# yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# Installed:
#   docker-ce-3:26.1.3-1.el8.x86_64
#   docker-ce-cli-1:26.1.3-1.el8.x86_64
#   containerd.io-1.6.32-3.1.el8.x86_64
#   docker-buildx-plugin-0.14.0-1.el8.x86_64
#   docker-compose-plugin-2.27.0-1.el8.x86_64

🚀 启动 Docker 服务

[root@docker_server ~]# systemctl enable docker --now
# Created symlink /etc/systemd/system/multi-user.target.wants/docker.service

[root@docker_server ~]# systemctl enable docker.service --now
[root@docker_server ~]# systemctl restart docker

🔧 配置镜像加速与远程访问

# 配置 daemon.json(镜像加速 + 远程 API)
[root@docker_server ~]# vi /etc/docker/daemon.json

# 安装 vim 后修改 docker.service 开启 TCP 监听
[root@docker_server ~]# yum install -y vim
[root@docker_server ~]# vim /usr/lib/systemd/system/docker.service

# 重新加载配置并重启
[root@docker_server ~]# systemctl daemon-reload
[root@docker_server ~]# systemctl restart docker.service

# 确认配置生效
[root@docker_server ~]# docker info

# 关闭防火墙(或放行 2375 端口)
[root@docker_server ~]# systemctl stop firewalld

2️⃣ 拉取镜像与运行容器

📥 拉取镜像

[root@docker ~]# docker pull centos:7
[root@docker ~]# docker images centos:7
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
centos        7         eeb6ee3f44bd   10 months ago  204MB

# 确认 Docker 版本
[root@docker ~]# docker --version
Docker version 26.1.3, build b72abfb

🏃 运行容器

# 查看宿主机内核版本
[root@docker ~]# uname -r

# 运行 Ubuntu 容器
[root@docker ~]# docker run -it ubuntu

# 运行 CentOS 7 容器
[root@docker ~]# docker run -it centos:7

📦 在容器内操作

# 进入容器后查看内核(与宿主机共享内核)
[root@37ddb0280728 /]# uname -r

# 容器内安装工具包
[root@37ddb0280728 /]# yum install -y bash-completion vim open-vm-tools lrzsz unzip rsync sshpass

# 退出容器
[root@37ddb0280728 /]# exit

🛠️ 在宿主机安装工具包

[root@docker ~]# yum install -y bash-completion vim open-vm-tools lrzsz unzip rsync sshpass
# Installed: bash-completion, sshpass, unzip, rsync, lrzsz, pkgconf, pkg-config 等

3️⃣ 配置终端提示符(PS1)

🎨 自定义带时间戳的彩色 PS1

[root@docker ~]# cat >> /etc/bashrc <<'EOF'
PS1='[\e[91m\u\e[93m@\e[92;1m\h\e[0m \e[94m\W\e[0m \e[35m\t\e[0m]\e[93m$\e[0m '
HISTTIMEFORMAT="%F %T "
EOF

# 重新加载 bash 配置
[root@docker ~]# bash

# 新提示符效果:[root@docker ~ 15:23:14]#

4️⃣ Docker Client 配置(192.168.108.31)

📦 安装依赖

[root@docker_client ~]# yum install -y yum-utils device-mapper-persistent-data
# ✅ yum-utils 安装完成

📥 添加 Docker CE 源

[root@docker_client ~]# yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# Adding repo from: https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# 更新缓存
[root@docker_client ~]# yum makecache
# Metadata cache created.

📥 仅安装 Client 工具

[root@docker_client ~]# yum install -y docker-ce-cli
# Installed:
#   docker-ce-cli-1:26.1.3-1.el8.x86_64
#   docker-buildx-plugin-0.14.0-1.el8.x86_64
#   docker-compose-plugin-2.27.0-1.el8.x86_64

🔗 远程连接测试

# ❌ 本地无 daemon,直接运行报错
[root@docker_client ~]# docker run hello-world
docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock.

# ✅ 通过 -H 远程连接 Server 的 Docker Daemon
[root@docker_client ~]# docker -H 192.168.108.30 run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

📋 查看远程镜像

[root@docker_client ~]# docker -H 192.168.108.30 images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
hello-world   latest    e2ac70e7319a   3 months ago   10.1kB

⚠️ 踩坑记录

#问题解决
1️⃣yum-config-manager --add-repo 没带 URL必须加上 https://... 完整地址
2️⃣systemctl enable docker.server 拼错正确是 docker.service
3️⃣Client 默认连本地 socket 报错必须加 -H <server_ip> 指定远程
4️⃣Server 没配 TCP 监听时 Client 连不上需修改 daemon.json + docker.service 开启远程端口
5️⃣防火墙拦截远程连接放行 2375 端口或 systemctl stop firewalld

5️⃣ 容器操作进阶

🐧 运行 Ubuntu 容器

[root@docker ~ 15:23:14]# docker run -it ubuntu
root@51cc2ef28e69:/#

📦 在 Ubuntu 容器内安装软件

# 更新包索引
root@51cc2ef28e69:/# apt-get update
# Fetched 24.6 MB in 29s

# 安装 vim
root@51cc2ef28e69:/# apt-get install -y vim
# 17 个新包安装完成(17.5 MB)

# ⚠️ 容器内没有 docker 命令
root@51cc2ef28e69:/# docker ps
bash: docker: command not found

# 退出容器
root@51cc2ef28e69:/# exit
exit

📋 查看运行中的容器

# 新窗口查看正在运行的容器
[root@docker / 15:49:16]# docker ps
CONTAINER ID   IMAGE     COMMAND       CREATED              STATUS              PORTS     NAMES
84ccdfaad19a   ubuntu    "/bin/bash"   About a minute ago   Up About a minute             reverent_haibt

💾 提交容器为新镜像

# 将安装了 vim 的容器提交为新镜像
# reverent_haibt 是容器名,ubuntu-with-vim 是新镜像名
[root@docker ~ 15:50:54]# docker commit reverent_haibt ubuntu-with-vim
sha256:5b395b8ca75c12ae15f7a1296c2ae94a70a35344fba726243b41d95d2890781d

💡 docker commit 可以将一个容器的当前状态保存为新镜像,常用于定制化基础镜像

# 新窗口查看正在运行的容器
[root@docker ~ 15:52:34]# docker images
REPOSITORY        TAG       IMAGE ID       CREATED              SIZE
ubuntu-with-vim   latest    5b395b8ca75c   About a minute ago   100MB
ubuntu            latest    5a4c6b929c57   2 weeks ago          100MB
centos            7         eeb6ee3f44bd   4 years ago          204MB


6️⃣ 使用 Dockerfile 构建镜像

📝 编写 Dockerfile

[root@docker ~ 16:26:40]# vim Dockerfile

# Dockerfile 内容如下:
FROM ubuntu
RUN apt-get update && apt-get install -y vim

🔨 构建镜像

[root@docker ~ 16:27:27]# docker build -t ubuntu-with-vim-dockerfile .
[+] Building 30.3s (6/6) FINISHED
 => [internal] load build definition from Dockerfile
 => [internal] load metadata for docker.io/library/ubuntu:latest
 => [1/2] FROM docker.io/library/ubuntu:latest
 => [2/2] RUN apt-get update && apt-get install -y vim    29.9s
 => exporting to image
 => naming to docker.io/library/ubuntu-with-vim-dockerfile

💡 对比:之前用 docker commit 制作镜像(手动操作),这里用 Dockerfile 构建(自动化、可重复、可版本控制),后者是生产环境的推荐方式。

📋 查看所有镜像

[root@docker ~ 16:28:31]# docker images
REPOSITORY                   TAG       IMAGE ID       CREATED          SIZE
ubuntu-with-vim-dockerfile   latest    81cc66830d72   30 seconds ago   215MB    # 📄 Dockerfile 构建
ubuntu-with-vim              latest    5b395b8ca75c   37 minutes ago   100MB    # 💾 docker commit 制作
ubuntu                       latest    5a4c6b929c57   2 weeks ago      100MB    # 🐧 官方基础镜像
centos                       7         eeb6ee3f44bd   4 years ago      204MB    # 🏛️ CentOS 7 基础镜像

📖 Docker 核心概念

🏗️ 整体架构

┌─────────────────┐     ┌──────────────────────┐     ┌──────────────┐
│  Docker Client   │────▶│   Docker Daemon       │────▶│   Registry    │
│  (docker CLI)    │     │   (dockerd)           │     │   (镜像仓库)   │
└─────────────────┘     └──────────────────────┘     └──────────────┘
                                │
                         ┌──────┴──────┐
                         ▼             ▼
                   ┌──────────┐  ┌──────────┐
                   │  Image   │  │ Container│
                   │  (镜像)   │  │  (容器)   │
                   └──────────┘  └──────────┘
组件说明
Image(镜像)只读模板,包含运行环境和应用代码,类似 ISO 文件
Container(容器)镜像的运行实例,可读可写,类似虚拟机
Dockerfile自动化构建镜像的脚本,每行指令生成一个层(Layer)
Registry(仓库)存储和分发镜像的地方(Docker Hub、阿里云 ACR 等)

📚 常用命令详解

🐳 docker pull — 拉取镜像

docker pull [选项] 镜像名[:标签]

# 常用选项:
#   -a         拉取所有标签的镜像
#   --platform 指定平台架构(linux/amd64, linux/arm64)

# 示例
docker pull centos:7            # 拉取指定标签
docker pull ubuntu              # 不指定标签默认 latest
docker pull --platform linux/arm64 ubuntu  # 拉取 ARM 架构版本

🖼️ docker images — 查看镜像列表

docker images [选项] [仓库名[:标签]]

# 常用选项:
#   -q          只显示镜像 ID(常用于组合命令)
#   --filter    过滤(--filter dangling=true)
#   --format    自定义输出格式

# 示例
docker images                    # 列出所有镜像
docker images ubuntu             # 只看 ubuntu 相关
docker images -q                 # 只显示 ID,可配合 rmi 批量删除

🏃 docker run — 运行容器

docker run [选项] 镜像名 [命令]

# 常用选项:
#   -it         交互式终端(-i 交互 + -t 分配终端)
#   -d          后台运行(detach)
#   --name      指定容器名
#   -p          端口映射(宿主机:容器)
#   -v          挂载卷(卷:容器路径)
#   -e          设置环境变量
#   --rm        退出后自动删除容器

# 示例
docker run -it ubuntu bash              # 交互式运行
docker run -d --name web -p 80:80 nginx # 后台运行 + 端口映射
docker run --rm -it centos:7            # 用完即删

📋 docker ps — 查看容器

docker ps [选项]

# 常用选项:
#   -a    显示所有容器(包括已停止的)
#   -q    只显示容器 ID
#   -l    显示最近创建的容器
#   -n    显示最近 n 个容器

# 示例
docker ps              # 只看运行中
docker ps -a           # 看所有(含已停止)
docker ps -a -q        # 只拿 ID,可配合 rm 批量删除

💾 docker commit — 提交容器为新镜像

docker commit [选项] 容器名/ID 新镜像名[:标签]

# 常用选项:
#   -a      作者信息
#   -m      提交信息(类似 git commit -m)
#   -p      提交时暂停容器

# 示例
docker commit reverent_haibt ubuntu-with-vim   # 提交容器为新镜像
docker commit -m "安装了vim" -a "ningcode" ubuntu-with-vim

# ⚠️ 注意:commit 制作镜像不推荐用于生产,
#    因为不可重复、不透明,建议用 Dockerfile

🔨 docker build — 从 Dockerfile 构建镜像

docker build [选项] 路径

# 常用选项:
#   -t          指定镜像名:标签(name:tag)
#   -f          指定 Dockerfile 路径(默认 ./Dockerfile)
#   --no-cache  构建时不使用缓存
#   --platform  指定目标平台

# Dockerfile 常用指令:
#   FROM        基础镜像(必须是第一行)
#   RUN         执行命令(每一条 RUN 生成一个层)
#   COPY        复制文件到镜像
#   ADD         复制文件(自动解压 tar)
#   CMD         容器启动时的默认命令
#   ENTRYPOINT  容器入口点
#   EXPOSE      声明端口
#   ENV         设置环境变量
#   WORKDIR     设置工作目录

# 示例
docker build -t myapp:v1 .                              # 构建
docker build -t myapp:v1 -f Dockerfile.prod .           # 指定文件
docker build --no-cache -t myapp:v1 .                   # 强制重新构建
~~~

---

## ⚠️ 踩坑记录

| # | 问题 | 解决 |
|---|------|------|
| 1️⃣ | `yum-config-manager --add-repo` 没带 URL | 必须加上 `https://...` 完整地址 |
| 2️⃣ | `systemctl enable docker.server` 拼错 | 正确是 `docker.service` |
| 3️⃣ | Client 默认连本地 socket 报错 | 必须加 `-H <server_ip>` 指定远程 |
| 4️⃣ | Server 没配 TCP 监听时 Client 连不上 | 需修改 `daemon.json` + `docker.service` 开启远程端口 |
| 5️⃣ | 防火墙拦截远程连接 | 放行 2375 端口或 `systemctl stop firewalld` |
| 6️⃣ | 容器内没有 docker 命令 | 容器是隔离环境,需挂载 docker.sock 才能从容器内执行 docker |
| 7️⃣ | `docker commit` vs `Dockerfile` 选哪个 | 生产环境用 **Dockerfile**(可重复、可追溯),commit 只适合临时调试 |

更多推荐