13 10 月 2026

"在我机器上能跑"是部署的经典难题。Docker 把程序连同运行环境打包成镜像,到哪都能一致运行。

这篇讲 Docker 的安装、核心概念、常用命令,以及如何用容器跑起一个 Web 应用。

容器需要一台能装 Docker 的服务器。财富云计算 提供云服务器;内网服务、测试环境可选 NAT 型(无独立公网 IP,价格比带独立 IP 机型省一半以上)。

一、为什么用 Docker

好处说明
环境一致开发、测试、生产完全一致
部署简单一条命令启动,不用装依赖
隔离性应用互不干扰,依赖不冲突
快速扩容起多个容器就是扩容
易于回滚换个镜像版本即可
资源占用小比虚拟机轻量得多

什么时候不需要 Docker:

  • 单一简单应用(直接装更快)
  • 对性能极致敏感
  • 不熟悉容器概念且团队也没人熟悉

二、安装

Ubuntu / Debian

# 官方一键脚本(最省事)
curl -fsSL https://get.docker.com | bash

# 或手动装
apt update
apt install ca-certificates curl gnupg -y
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" > /etc/apt/sources.list.d/docker.list
apt update
apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y

systemctl enable --now docker
docker --version

CentOS / Rocky

yum install -y yum-utils
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
systemctl enable --now docker

免 sudo 使用

usermod -aG docker $USER
newgrp docker        # 或重新登录
docker ps            # 测试
⚠️ docker 组等同于 root 权限(可以挂载宿主机目录),只给可信用户。

配置镜像加速(国内)

mkdir -p /etc/docker
nano /etc/docker/daemon.json
{
  "registry-mirrors": ["https://docker.m.daocloud.io"]
}
systemctl restart docker
docker info | grep -A 3 "Registry Mirrors"

三、三个核心概念

概念类比说明
镜像(Image)程序安装包 / 模板只读,包含运行环境和程序
容器(Container)运行中的程序镜像的运行实例,可读写
仓库(Registry)应用商店存放镜像(Docker Hub 等)
Docker Hub → docker pull → 本地镜像 → docker run → 容器

四、镜像操作

# 搜索
docker search nginx

# 拉取
docker pull nginx                  # 最新版
docker pull nginx:1.25             # 指定版本
docker pull nginx:1.25-alpine      # 精简版(推荐,体积小)

# 查看本地镜像
docker images
docker images -a

# 删除镜像
docker rmi nginx:1.25
docker rmi $(docker images -q)     # 删除所有镜像(危险)

# 查看镜像详情
docker inspect nginx

# 构建镜像
docker build -t myapp:v1 .

# 打标签
docker tag myapp:v1 myrepo/myapp:v1

# 推送
docker push myrepo/myapp:v1

# 清理无用镜像
docker image prune
docker image prune -a              # 包括未被使用的

五、容器操作

运行容器

# 基本运行
docker run nginx

# 后台运行 + 命名
docker run -d --name my-nginx nginx

# 端口映射(宿主机 8080 → 容器 80)
docker run -d --name web -p 8080:80 nginx

# 只监听本地(更安全,配合 Nginx 反代)
docker run -d -p 127.0.0.1:8080:80 nginx

# 挂载目录(数据持久化)
docker run -d -v /data/html:/usr/share/nginx/html nginx

# 挂载文件
docker run -d -v /my/nginx.conf:/etc/nginx/nginx.conf:ro nginx

# 环境变量
docker run -d -e MYSQL_ROOT_PASSWORD=123456 mysql:8

# 自动重启
docker run -d --restart=always nginx

# 交互式运行(调试用)
docker run -it ubuntu /bin/bash

# 运行完就删除(一次性任务)
docker run --rm alpine echo "hello"

最常用组合:

docker run -d --name app \
  --restart=always \
  -p 127.0.0.1:8080:80 \
  -v /data/app:/app \
  -e TZ=Asia/Shanghai \
  nginx:alpine

查看与管理

docker ps                 # 运行中的容器
docker ps -a              # 所有(含已停止)
docker ps -q              # 只显示 ID

docker start app          # 启动
docker stop app           # 停止
docker restart app        # 重启
docker pause app          # 暂停
docker unpause app        # 继续
docker kill app           # 强制停止

docker rm app             # 删除(需先停止)
docker rm -f app          # 强制删除运行中的
docker rm $(docker ps -aq)    # 删除所有容器(危险)

docker logs app           # 查看日志
docker logs -f app        # 实时跟踪
docker logs --tail 100 app
docker logs -t app        # 带时间戳

进入容器

docker exec -it app /bin/bash      # 进入并开 shell
docker exec -it app /bin/sh        # alpine 用 sh
docker exec app ls /app            # 执行单条命令
docker exec -u root -it app bash   # 以 root 进入

文件拷贝

docker cp app:/etc/nginx/nginx.conf ./nginx.conf      # 从容器拷出
docker cp ./file.txt app:/tmp/                        # 拷进容器

资源查看

docker stats              # 实时资源占用
docker stats app
docker top app            # 容器内进程
docker inspect app        # 详细信息(IP、挂载、配置等)
docker port app           # 端口映射
docker diff app           # 文件改动

六、数据持久化

容器删除后数据就没了,所以数据要挂载出来。

三种方式

1)bind mount(挂载宿主机目录)

docker run -d -v /data/mysql:/var/lib/mysql mysql:8

直接挂载宿主机的具体路径,直观、方便备份。

2)volume(数据卷,推荐)

docker volume create mydata
docker run -d -v mydata:/var/lib/mysql mysql:8

docker volume ls
docker volume inspect mydata
docker volume rm mydata
docker volume prune          # 清理未使用的

由 Docker 管理,跨平台一致,推荐生产使用。

3)tmpfs(内存)

docker run -d --tmpfs /tmp nginx

七、网络

docker network ls
docker network create mynet
docker network inspect mynet
docker network rm mynet
# 容器加入自定义网络(容器间可用名字互访)
docker run -d --name db --network mynet mysql:8
docker run -d --name app --network mynet myapp
# app 里可以直接用 db 作为主机名访问数据库

端口映射写法:

-p 8080:80              # 宿主机 8080 → 容器 80
-p 127.0.0.1:8080:80    # 只监听本地(推荐)
-p 8080:80/udp          # UDP
-P                      # 随机映射

八、实战:跑一个 Nginx 网站

# 1. 建目录
mkdir -p /data/site
echo "<h1>Hello Docker</h1>" > /data/site/index.html

# 2. 启动容器
docker run -d --name myweb \
  --restart=always \
  -p 127.0.0.1:8080:80 \
  -v /data/site:/usr/share/nginx/html:ro \
  nginx:alpine

# 3. 验证
curl http://127.0.0.1:8080

# 4. 用宿主机 Nginx 反代对外

宿主机 Nginx:

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

关键做法:容器只监听 127.0.0.1,用宿主机 Nginx 反代对外,这样:

  • 容器不会绕过防火墙
  • 统一的 HTTPS 和域名管理
  • 更安全

九、Dockerfile(构建自己的镜像)

# Dockerfile
FROM node:18-alpine

WORKDIR /app

COPY package*.json ./
RUN npm ci --production

COPY . .

EXPOSE 3000

ENV NODE_ENV=production

CMD ["node", "server.js"]
docker build -t myapp:v1 .
docker run -d -p 3000:3000 myapp:v1

常用指令:

指令作用
FROM基础镜像
WORKDIR工作目录
COPY / ADD复制文件
RUN构建时执行命令
ENV环境变量
EXPOSE声明端口
CMD容器启动命令(可被覆盖)
ENTRYPOINT入口命令
USER指定运行用户
HEALTHCHECK健康检查

优化建议:

# ✅ 用 alpine 精简镜像
FROM node:18-alpine

# ✅ 先 COPY 依赖文件再安装,利用缓存
COPY package*.json ./
RUN npm ci
COPY . .

# ✅ 用非 root 用户
USER node

# ✅ .dockerignore 排除不需要的文件

.dockerignore:

node_modules
.git
.env
*.log

十、清理与维护

# 查看占用
docker system df

# 清理
docker container prune      # 停止的容器
docker image prune -a       # 无用镜像
docker volume prune         # 无用卷
docker network prune        # 无用网络
docker system prune -a      # 全部清理(危险,会删掉未运行的一切)

# 日志清理(容器日志可能很大)
ls -lh /var/lib/docker/containers/*/*-json.log
truncate -s 0 /var/lib/docker/containers/*/*-json.log

限制日志大小:

// /etc/docker/daemon.json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}
systemctl restart docker

十一、安全建议

  • [ ] 不用 --privileged
  • [ ] 不挂载 /var/run/docker.sock(等于给 root)
  • [ ] 容器进程不用 root(USER 指令)
  • [ ] 只监听 127.0.0.1,用 Nginx 反代
  • [ ] 用官方可信镜像
  • [ ] 定期更新镜像(漏洞修复)
  • [ ] 限制容器资源(--memory、--cpus)
  • [ ] 敏感信息用环境变量或 secret,不写进镜像
docker run -d --memory=512m --cpus=1 myapp

十二、速查表

docker pull 镜像                    拉取
docker images                       镜像列表
docker run -d --name x -p 80:80 img 运行
docker ps -a                        容器列表
docker start/stop/restart x         启停
docker logs -f x                    日志
docker exec -it x bash              进入
docker rm -f x                      删除
docker system df                    占用
docker system prune -a              清理

docker volume create/ls/rm          数据卷
docker network create/ls            网络
docker build -t name .              构建
docker stats                        资源

容器化部署能大幅简化运维。财富云计算 的云服务器完整支持 Docker,可自由部署容器应用;内部服务、测试环境可选 NAT 型(无独立公网 IP,价格比带独立 IP 机型省一半以上),配合端口映射按需暴露服务。

相关阅读:

  • 《Docker Compose 编排实战》
  • 《Docker 常见故障排查》
  • 《Nginx 反向代理与多站点配置》
延伸阅读
  1. 网站环境怎么选:LNMP 手动 / 宝塔面板 / Docker / 云开发
  2. 问卷表单系统搭建:SurveyKing / Formbricks,数据自己收
  3. 图床搭建:Lsky Pro / Lychee,自托管图片托管方案
  4. 邮件列表搭建:listmonk 自托管 Newsletter,把读者握在自己手里
  5. 文档站点搭建:MkDocs / VuePress / Docsify,产品文档与技术手册方案
  6. RSS 阅读器搭建:FreshRSS 自托管,把信息流拿回自己手里
  7. 短链接服务搭建:Shlink 自托管,链接数据自己掌握
  8. 网站状态监控页搭建:Uptime Kuma,服务器挂了第一时间知道
更多阅读
  1. 上一篇:Redis 安装与缓存应用实战:给数据库减负的最快手段
  2. 下一篇:Docker Compose 编排实战:一条命令启动整套服务
发表评论 5

取消回复