1. 为什么选择在Ubuntu上使用Docker?
作为Linux发行版中的常青树,Ubuntu凭借其稳定的软件源和活跃的社区支持,成为运行Docker的理想平台。我在多个生产环境中实测发现,Ubuntu LTS版本与Docker的兼容性表现最佳,特别是对于需要长期运行的容器服务。Docker带来的环境隔离和快速部署特性,能完美解决开发环境与生产环境不一致这个困扰开发者多年的"玄学问题"。
举个例子,我们团队曾经有个Python项目在本地测试一切正常,但部署到服务器就出现依赖冲突。改用Docker容器化部署后,只需将包含所有依赖的镜像推送到服务器即可运行,彻底告别了"在我机器上好好的"这类经典问题。下面这张示意图展示了传统部署与容器化部署的差异:
传统部署: [开发者环境] -> 手动安装依赖 -> 代码部署 -> 环境差异导致问题 容器化部署: [Docker镜像] -> 一键部署 -> 环境完全一致2. 安装前的准备工作
2.1 系统环境检查
在开始安装前,建议先确认你的Ubuntu版本是否符合要求。执行以下命令查看系统信息:
lsb_release -a # 输出示例: # No LSB modules are available. # Distributor ID: Ubuntu # Description: Ubuntu 22.04.3 LTS # Release: 22.04 # Codename: jammy注意:虽然Docker支持多个Ubuntu版本,但建议使用18.04 LTS及以上版本以获得最佳兼容性。我在20.04和22.04 LTS上都有长期稳定运行的Docker生产环境。
2.2 彻底卸载旧版本
如果你之前安装过Docker或其他容器运行时,强烈建议先执行彻底清理。我曾经遇到过因为旧版本残留导致新安装异常的情况,以下是经过验证的完整清理方案:
# 停止所有运行中的容器 sudo docker stop $(sudo docker ps -aq) # 删除所有容器、镜像、卷和网络 sudo docker system prune -a --volumes # 卸载旧版Docker及相关组件 sudo apt remove --purge docker.io docker-compose docker-doc podman-docker containerd runc # 清理残留配置文件 sudo rm -rf /var/lib/docker sudo rm -rf /etc/docker这个清理过程会删除所有Docker数据,所以如果存在需要保留的容器或镜像,请提前做好备份。
3. 安装Docker引擎
3.1 设置软件仓库
Ubuntu的apt包管理器默认不包含Docker官方源,我们需要手动添加。以下是详细步骤:
- 安装必要的工具包:
sudo apt update sudo apt install -y ca-certificates curl gnupg lsb-release- 添加Docker官方GPG密钥:
sudo mkdir -p /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg经验之谈:我曾经因为网络问题导致密钥下载不完整,可以通过
gpg --show-keys /etc/apt/keyrings/docker.gpg验证密钥是否有效。正常应该显示Docker的密钥指纹:9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88
- 设置稳定版仓库:
echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null3.2 安装Docker引擎
更新apt索引并安装最新版Docker:
sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin验证安装是否成功:
sudo docker run hello-world如果看到"Hello from Docker!"的消息,说明安装成功。我第一次看到这个提示时,花了5分钟研究这个hello-world镜像到底是怎么工作的 - 它实际上是个极简的Linux镜像,只包含一个输出文本的可执行文件。
4. 配置优化
4.1 国内镜像加速
默认的Docker Hub在国内访问速度较慢,我们可以配置镜像加速器。这是我收集的几个稳定镜像源:
sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": [ "https://hub-mirror.c.163.com", "https://mirror.baidubce.com", "https://docker.mirrors.ustc.edu.cn" ], "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m" }, "storage-driver": "overlay2" } EOF配置后需要重启Docker服务:
sudo systemctl daemon-reload sudo systemctl restart docker验证配置是否生效:
docker info | grep -A 10 "Registry Mirrors"4.2 非root用户操作Docker
默认情况下,只有root用户和sudo用户才能运行Docker命令。为了安全和使用方便,可以将当前用户加入docker组:
sudo usermod -aG docker $USER newgrp docker # 刷新组权限安全提示:docker组实际上具有root权限,因此只应添加可信用户。在生产环境中,我通常会配置更细粒度的权限控制。
5. 数据存储管理
5.1 存储目录结构解析
Docker默认将所有数据存储在/var/lib/docker目录下,其结构如下:
/var/lib/docker/ ├── buildkit/ # 构建缓存 ├── containers/ # 容器运行时数据 ├── image/ # 镜像存储 ├── network/ # 网络配置 ├── overlay2/ # 存储驱动数据 ├── plugins/ # 插件 ├── swarm/ # Swarm集群数据 └── volumes/ # 数据卷这个目录会随着使用不断增长,我曾经遇到过一个生产环境因为日志文件未配置轮转,导致磁盘被占满的情况。
5.2 更改数据存储位置
对于SSD容量有限的开发机,或者需要将Docker数据存储在独立磁盘的场景,可以修改数据存储位置:
- 停止Docker服务:
sudo systemctl stop docker- 迁移现有数据(可选):
sudo rsync -avxP /var/lib/docker/ /new/path/docker/- 修改配置文件:
sudo tee /etc/docker/daemon.json <<-'EOF' { "data-root": "/new/path/docker" } EOF- 重启服务:
sudo systemctl start docker迁移技巧:使用rsync而不是直接mv,可以在迁移失败时回退。我曾在一个10TB数据的迁移中,因为使用mv导致服务中断了3小时。
6. 日常使用技巧
6.1 服务管理命令
# 查看状态 sudo systemctl status docker # 设置开机自启 sudo systemctl enable docker # 查看日志 sudo journalctl -u docker -f6.2 空间清理
随着使用,Docker会积累大量无用数据,定期清理可以节省空间:
# 删除所有停止的容器 docker container prune # 删除所有未被使用的镜像 docker image prune -a # 全面清理(包括构建缓存) docker system prune -a --volumes我在crontab中设置了每周自动清理:
0 3 * * 0 docker system prune -f6.3 常见问题排查
问题1:docker命令报权限错误
解决:
sudo usermod -aG docker $USER newgrp docker问题2:端口冲突
解决:
# 查看端口占用 sudo netstat -tulnp | grep <端口号> # 或者使用现代替代方案 sudo ss -tulnp | grep <端口号>问题3:磁盘空间不足
解决:
# 查看Docker磁盘使用 docker system df # 清理 docker system prune -a --volumes7. 进阶配置
7.1 日志配置
默认情况下,Docker容器日志会无限增长。我们可以限制日志大小:
{ "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" } }7.2 存储驱动选择
对于Ubuntu,推荐使用overlay2存储驱动。可以通过以下命令验证:
docker info | grep "Storage Driver"7.3 生产环境建议
- 配置监控:使用
docker stats或Prometheus监控容器资源使用情况 - 资源限制:通过
--memory和--cpus参数限制容器资源 - 备份策略:定期备份重要的数据卷
我在生产环境中通常会配置如下资源限制:
docker run -d --name myapp \ --memory 1g \ --cpus 2 \ --restart unless-stopped \ myapp-image8. 容器化开发实践
8.1 开发环境搭建
使用Docker可以快速搭建一致的开发环境。例如,对于Python项目:
FROM python:3.9-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . CMD ["python", "app.py"]然后通过docker-compose.yml管理服务依赖:
version: '3' services: web: build: . ports: - "5000:5000" volumes: - .:/app depends_on: - redis redis: image: redis:alpine8.2 持续集成
在CI/CD流水线中使用Docker可以确保构建环境一致。以下是GitLab CI的示例配置:
build: image: docker:20.10 services: - docker:dind script: - docker build -t myapp . - docker run myapp pytest8.3 性能优化技巧
- 使用.dockerignore文件减少构建上下文大小
- 多阶段构建减小镜像体积
- 合理利用构建缓存
这是我常用的多阶段构建示例:
# 构建阶段 FROM golang:1.18 as builder WORKDIR /app COPY . . RUN go build -o myapp # 运行阶段 FROM alpine:latest WORKDIR /root/ COPY --from=builder /app/myapp . CMD ["./myapp"]这种构建方式可以将Go应用的镜像从300MB+减小到10MB左右。