Docker 的价值在于把「装环境」变成「拉镜像 + 一份 compose 文件」。这篇从一台干净的 Ubuntu 24.04 开始,装官方版 Docker、配好日常使用的基础设置,再跑一个能被 Nginx 反代的容器。

一、先卸掉冲突包

Docker 官方文档写得很直接:发行版自带的 Docker 包可能与官方包冲突,安装官方版前要先卸载。

sudo apt remove $(dpkg --get-selections docker.io docker-compose docker-compose-v2 docker-doc docker-buildx podman-docker containerd runc | cut -f1)

如果提示没有可卸载的包,跳过即可。

二、用官方仓库安装

sudo apt update
sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF

sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

装完验证:

docker version
docker compose version

两个都有输出就说明 Engine 和 Compose 插件都到位了。Compose 是插件形式,命令写作 docker compose,不是旧的 docker-compose。

三、开机自启

sudo systemctl enable --now docker.service
sudo systemctl enable --now containerd.service

--now 表示同时启动。重启机器后容器会自动恢复(配合 compose 里的 restart 策略)。

四、让普通用户能用 docker

官方说明:守护进程监听的是 Unix socket,默认属主是 root,所以其他用户只能靠 sudo 访问。

sudo groupadd docker          # 组已存在会提示,忽略
sudo usermod -aG docker $USER
newgrp docker

重新登录后 docker ps 不再需要 sudo。

安全提醒:官方明确写了 docker 组授予的是 root 级权限。只把可信账号加进去,别给临时用户。

五、限制日志大小(很重要)

默认日志驱动是 json-file,不设上限会一直增长。新建 /etc/docker/daemon.json:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

然后:

sudo systemctl restart docker

注意:日志配置在容器创建时生效,已有容器要重建(docker compose up -d --force-recreate)才会应用。

六、用 Compose 跑一个容器

建目录:

mkdir -p /opt/demo/html
cd /opt/demo

写一个静态页:

echo '<h1>hello from container</h1>' > html/index.html

新建 compose.yaml:

services:
  web:
    image: nginx:alpine
    ports:
      - "127.0.0.1:8080:80"
    volumes:
      - ./html:/usr/share/nginx/html:ro
    restart: unless-stopped

启动:

docker compose up -d

解释几个点:

  • ports 写成 127.0.0.1:8080:80,只绑本机,外网访问不到,交给宿主 Nginx 反代;
  • ./html:/usr/share/nginx/html:ro 是绑定挂载,改文件不用重建容器;
  • restart: unless-stopped 让容器随 Docker 启动而恢复。

验证:

curl -I http://127.0.0.1:8080

七、常用命令

目的 命令
后台启动 docker compose up -d
看状态 docker compose ps
跟踪日志 docker compose logs -f web
进容器 docker compose exec web sh
重建 docker compose up -d --force-recreate
拉新镜像并更新 docker compose pull && docker compose up -d
停止并移除容器与网络 docker compose down
查看占用 docker system df

docker compose down -v 会连命名卷一起删。有数据时别顺手加 -v。

八、数据放在哪

两种方式:

  • 命名卷(volumes: - dbdata:/var/lib/mysql):由 Docker 管理,备份要进容器或临时容器打包;
  • 绑定挂载(./data:/var/lib/mysql):数据就在宿主机目录里,备份直接拷目录,更直观。

数据库、上传目录这类必须持久化的数据,两者选一种并写清楚,别用「容器删了数据也没了」的默认行为。

九、安全底线

  1. 不要暴露 2375/2376:未加密的 Docker API 等于把 root 交给公网;
  2. 容器端口只发布到 127.0.0.1,由宿主 Nginx 统一做 TLS;
  3. 镜像只从可信仓库拉,固定标签,别长期用 latest;
  4. 定期更新:docker compose pull 后再 up -d,更新前先备份数据卷;
  5. 容器内不以 root 跑业务进程(镜像支持 user: 时优先用)。

十、常见问题对照

现象 原因与处理
permission denied ... docker.sock 未加入 docker 组,或没重新登录
port is already allocated 宿主已有服务占用该端口,换端口或先停旧服务
容器启动后立刻退出 docker compose logs 看应用报错,多数是配置或权限
磁盘快速变满 docker system df 看镜像/日志/卷;prune 前确认没有要保留的卷
docker compose 不存在 缺 docker-compose-plugin,按第二节装
改了 daemon.json 不生效 没重启 Docker;已有容器需重建

一句话总结

官方仓库装 Engine 与 Compose 插件 → 加 docker 组免 sudo → 限制日志 → 用 compose.yaml 描述服务 → 端口只绑 127.0.0.1 交给 Nginx。 数据要么进命名卷、要么进绑定目录,先想清楚备份怎么取。