Docker 意义、更新流程与镜像仓库

2026年4月30日 Nginx_Docker 12 分钟阅读 21 次阅读
📖 文章摘要

深入理解 Docker 解决的核心问题,讲解容器与源码的关系、项目更新流程、镜像仓库使用方法与标签策略

一、Docker 到底解决了什么问题

场景:博客部署

没有 Docker 时,部署博客要这样做:

  1. 服务器上装 Python 3.11 + pip + 所有依赖(fastapi、uvicorn、sqlalchemy...)
  2. 服务器上装 Node.js + npm + 所有依赖(nuxt、tailwindcss、vue...)
  3. 配置 Nginx 反向代理
  4. 用 systemd 管理服务
  5. 写部署脚本把代码传上去

问题来了:

  • 你换一台服务器,以上步骤全部重来一遍
  • 服务器系统升级了,依赖可能不兼容
  • 多个项目跑在同一台服务器上,Python 版本冲突怎么办?
  • "我本地跑得好好的,服务器上怎么就挂了?"

有了 Docker 之后:
Dockerfile 里已经写死了:用什么 Python 版本、装什么依赖、怎么启动。换一台服务器?docker compose up -d,完事。

三个核心好处

好处 没有 Docker 有 Docker
环境隔离 所有项目共享服务器的 Python、Node.js,版本冲突 每个容器有自己的环境,互不影响
可移植 换服务器要重新装环境 换服务器只要 Docker + 镜像,一条命令启动
一致性 "我本地能跑"是经典借口 Dockerfile 写死环境,本地和服务器完全一样

可移植性的实际场景

只有一台服务器的情况下是感受不到的。但在实际工作里:

  • 项目要部署到 3 台服务器(测试环境、预发布、生产环境)
  • 没有 Docker:3 台服务器分别装环境,每台都可能出问题
  • 有 Docker:把镜像推送到仓库,3 台服务器各拉一份跑起来,环境 100% 一样

二、容器和源码的关系

实验验证

在学习服务器上做了这个实验:

# 1. 确认博客正常运行
curl -I localhost:3000          # 返回 200 OK
curl localhost:8001/api/articles  # 返回正常 JSON

# 2. 删除整个源码目录
rm -rf ~/博客项目目录

# 3. 再次访问——容器还在跑,博客正常
curl -I localhost:3000          # 依然 200 OK
curl localhost:8001/api/articles  # 依然正常

结论:删了源码,容器不受影响。

为什么?

构建阶段:源码 + Dockerfile → docker build → 镜像(包含代码+依赖+环境)
运行阶段:镜像 → docker run → 容器(里面已经有代码了,不需要外面的源码)

镜像是一次性打包好的,容器运行时不依赖外面的文件。就像你把菜做好装进饭盒,饭盒里的菜不会因为你把厨房拆了就消失。

源码还是需要的

虽然删了源码容器还能跑,但不会真的删源码——源码在 Git 仓库里。源码的作用是:

  • 代码有 bug 要改
  • 功能要更新
  • 重新构建镜像时需要

三、博客更新流程

场景:改了博客代码,怎么更新服务器?

没有 Docker 时:

# 本地改完代码
git push

# 服务器上
ssh 用户名@你的服务器地址
cd ~/blog
git pull

# 重启服务
systemctl restart blog-api
systemctl restart blog-web

有 Docker 时:

# 服务器上
cd ~/项目目录
git pull                                    # 拉最新代码
docker compose up -d --build                # 重新构建镜像并启动

两条命令。--build 会重新执行 Dockerfile,用新代码构建新镜像,然后自动替换旧容器。

更新流程图

改了代码 → git push → 服务器 git pull → docker compose up -d --build
                                                    ↓
                                          重新构建镜像(用新代码)
                                                    ↓
                                          停掉旧容器 → 启动新容器

四、镜像仓库(Image Registry)

是什么

镜像仓库就是存 Docker 镜像的网盘。你构建好的镜像推送到仓库,其他服务器从仓库拉取。

类比:

  • GitHub 存代码
  • Docker Hub(镜像仓库)存镜像

常见的镜像仓库

仓库 说明
Docker Hub 官方公共仓库,免费(公开仓库)
阿里云容器镜像服务 国内快,免费
腾讯云容器镜像服务 国内快,免费
GitHub Container Registry GitHub 自带的
私有仓库 公司内部搭的(Harbor)

什么时候需要

场景 需不需要镜像仓库
只有一台服务器 不需要,本地构建就行
多台服务器部署 需要,不然每台都要构建一次
团队协作 需要,大家共用一份镜像
生产环境 建议用,保证镜像一致性

五、镜像仓库工作流程

完整流程

1. 本地构建镜像
   docker build -t blog-api .

2. 给镜像打标签(加上仓库地址)
   docker tag blog-api:latest registry.cn-hangzhou.aliyuncs.com/你的命名空间/blog-api:v1

3. 推送到仓库
   docker push registry.cn-hangzhou.aliyuncs.com/你的命名空间/blog-api:v1

4. 其他服务器拉取
   docker pull registry.cn-hangzhou.aliyuncs.com/你的命名空间/blog-api:v1

5. 其他服务器运行
   docker run -d -p 8001:8001 registry.cn-hangzhou.aliyuncs.com/你的命名空间/blog-api:v1

标签名的格式

registry地址/命名空间/镜像名:标签

例:registry.cn-hangzhou.aliyuncs.com/你的命名空间/blog-api:v1

  • registry.cn-hangzhou.aliyuncs.com:阿里云镜像仓库地址
  • 你的命名空间:你的命名空间(相当于文件夹)
  • blog-api:镜像名
  • v1:版本标签(不写默认 latest)

docker-compose 用仓库镜像

如果镜像已经推送到仓库,docker-compose.yml 可以改成:

services:
  backend:
    image: registry.cn-hangzhou.aliyuncs.com/你的命名空间/blog-api:v1   # 用仓库镜像,不用 build
    ports:
      - "8001:8001"
    volumes:
      - ./data:/app/data
    restart: always

  frontend:
    image: registry.cn-hangzhou.aliyuncs.com/你的命名空间/blog-web:v1
    ports:
      - "3000:3000"
    depends_on:
      - backend
    restart: always

image: 替代 build:,直接从仓库拉取镜像,不用本地构建。


六、部署方案演进

当前架构

学习服务器(测试环境)                生产服务器
Docker 容器化                          直接部署(systemd)
用于学习和测试                         线上运行

未来理想架构(生产也容器化)

你改代码 → git push
                ↓
        镜像仓库(阿里云/腾讯云)
                ↓
        ┌───────┴───────┐
        ↓               ↓
  学习服务器          生产服务器
  git pull            git pull
  docker compose      docker compose
  up -d --build       up -d --build

实际操作步骤

  1. 在学习服务器上构建镜像并推送到仓库
  2. 在生产服务器上拉取镜像
  3. 生产服务器也用 docker-compose 管理

七、镜像标签策略

为什么要打标签

  • latest 标签:latest 不是固定版本,每次 push 会覆盖
  • 版本标签:v1v220260705,方便回滚

推荐的标签命名

标签 含义
v1 v2 v3 语义化版本
20260705 日期标签
commit hash git 提交哈希(如 a1b2c3d)

回滚操作

如果新版本有 bug,想回到上一个版本:

# 用旧标签的镜像启动
docker run -d -p 8001:8001 registry.cn-hangzhou.aliyuncs.com/你的命名空间/blog-api:v1

八、常见问题

Q:Docker 容器删了数据还在吗?
看情况。如果用了卷挂载(-v),数据存在宿主机上,容器删了数据还在。如果没用卷,数据跟着容器一起没了。

Q:Docker 和虚拟机的区别?
Docker 容器共享宿主机内核,启动快(秒级)、占用资源少(MB级)。虚拟机有独立内核,启动慢(分钟级)、占用资源多(GB级)。Docker 适合微服务和快速部署,虚拟机适合需要强隔离的场景。

Q:Dockerfile 的分层缓存是什么?
Dockerfile 每条指令创建一层,Docker 会缓存每一层。如果某层没变化就用缓存,不重新构建。所以要把不常变的指令(如安装依赖)放前面,常变的(如复制代码)放后面。

Q:Docker 镜像怎么分发?
推送到镜像仓库(Docker Hub、阿里云等),其他服务器从仓库拉取。用 docker tag 给镜像打上仓库地址标签,然后 docker push。

Q:容器挂了怎么办?
docker-compose.yml 里配置 restart: always,容器挂了 Docker 自动重启。如果是 OOM(内存不足)被系统杀的,需要排查内存问题。

Q:Docker 数据持久化怎么做?
用 -v 参数挂载卷:docker run -v 宿主机路径:容器路径。数据存在宿主机上,容器删了数据还在。也可以用命名卷让 Docker 管理。

文章创建于:2026年4月30日CC BY-NC-SA 4.0

评论

暂无评论,来写第一条吧

别老叽霸扫描爆破后台了,个人博客能存啥有价值的东西,有这时间不如去扫俩放片的网站