Drioi
发布于 2026-10-13 / 9 阅读
0
0

那些年使用Docker踩过的坑

前言

之前做过一个小项目,需要把一套 Python 服务部署到服务器上,我就说试着玩玩 Docker 吧,听说一次打包就能到处跑,很省心(・ω・),而且网上Docker的教程也很多,当时觉得应该很快就能搞定了。结果从装好 Docker 到服务正常跑起来,我整整折腾了一个周末,这期间踩的坑不算高级,很多都能顺利解决,但还是有些坑让我很抓狂。今天就把这些坑记录下来,给刚入坑 Docker 的朋友避避雷。

第一个坑:docker ps 报权限不足

装好 Docker 之后,我兴冲冲地敲下第一个命令:

docker ps

结果直接甩我一脸报错:

Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.26/images/json: dial unix /var/run/docker.sock: connect: permission denied

难道我装错了吗?(;一_一)

查了一些相关知识才知道,Docker 进程默认用 Unix Socket 通信,这个 socket 文件属于 root 用户,普通用户没有访问权限。每次命令前加 sudo 能解决,但每敲一次就要输一次密码,就很烦。

永久解决办法是把当前用户加进 docker 用户组:

# 1. 创建 docker 用户组(已存在会提示,不用管)
sudo groupadd docker
# 2. 把当前登录用户加入 docker 用户组
sudo gpasswd -a $USER docker
# 3. 更新用户组,让设置立即生效
newgrp docker
# 4. 测试
docker ps

注意:newgrp docker 只对当前终端会话生效,如果你开了好几个终端,其他终端还是没权限,得重新登录或者每个终端都执行一遍。我一开始不知道,在另一个窗口敲 docker ps 还是报错,一度以为方法没生效。

第二个坑:docker attach 退出把容器搞停了

容器跑起来之后,我想进去看看里面的文件结构。

docker attach ubuntu-test

进去之后看了几眼,顺手敲了个 exit 想退出来,结果容器也跟着停了(╯°□°)╯︵ ┻━┻。

我当时就懵了,退个终端怎么把服务也退了?后来查了文档才知道,docker attach 连接到的是容器的主进程终端,你在里面敲 exit,等于把主进程结束了,容器自然就停了。

正确做法是用 docker exec:

docker exec -it ubuntu-test /bin/bash

exec 是在容器里新开一个进程,你退出的时候只结束这个新进程,容器本身继续在后台跑。

我后来养成了习惯,只要容器是在后台跑的,一律用 exec 进去,attach 基本不用了。

第三个坑:docker export 和 docker save 分不清

项目要迁移到另一台服务器,我想把容器打包带走。docker export 能把容器导出成 tar 文件,于是就用了:

docker export ubuntu-test > ubuntu1.tar

导出的文件拷到新服务器,用 docker import 导入:

cat ubuntu.tar | docker import - test/ubuntu:v1

导入成功了,镜像也生成了,但启动之后发现里面装的东西全没了,只剩下一个空壳系统。(´-ω-`)

折腾半天才搞明白,docker export 导出的是容器的文件系统快照,不包含镜像的层历史和元数据,而 docker save 导出的是镜像,保留完整的层结构和历史记录。这两个命令名字像,用途完全不同:

  1. docker export / import:操作对象是容器,导出文件系统,适合做容器快照备份。

  2. docker save / load:操作对象是镜像,保留完整层历史,适合迁移镜像。

我要迁移的是配置好的镜像,应该用 docker save 才对。

第四个坑:镜像下载慢到怀疑人生

第一次执行 docker pull ubuntu 的时候,我盯着终端看了五分钟,进度条纹丝不动。

Pulling from library/ubuntu

就这一行,然后没了。(;´д`)ゞ

原来Docker Hub 的服务器在国外,国内直接拉取经常慢到超时。解决办法是配置国内镜像源,在 /etc/docker/daemon.json 里加上:

{
  "registry-mirrors": [
    "https://docker.mirrors.ustc.edu.cn",
    "https://hub-mirror.c.163.com"
  ]
}

然后重启 Docker:

bash

sudo systemctl daemon-reload
sudo systemctl restart docker

配完之后速度确实快了不少。这里提醒一下,镜像源地址可能会有变动,用之前最好搜一下当前可用的源,有些老教程里的地址已经失效了。

第五个坑:容器删了,磁盘还占着

项目调了一段时间,我删了几个不用的容器:

docker rm -f ubuntu-test

以为这样删完就干净了。结果某天服务器磁盘告警,df -h 一看,根分区快满了。

用 docker system df 查了一下,发现 volume、镜像层、停止的容器 占了一大堆空间。原来 docker rm 只删容器本身,容器挂载的数据卷、构建产生的中间镜像层都还留着。

清理命令:

# 查看 Docker 磁盘占用
docker system df
# 清理停止的容器、无用镜像、无用网络
docker system prune
# 连数据卷一起清理(谨慎使用)
docker system prune --volumes

--volumes 这个参数要小心,它会删掉所有没被使用的数据卷。如果哪个卷里有重要数据,又刚好没被容器挂载,那就一起没了。

个人总结

折腾了念了很久的Docker,我的感受是:教程多,入门确实不难,但是需要注意细节。

  1. 权限问题:加 docker 用户组,注意 newgrp 只对当前终端生效。

  2. 进入容器:后台容器用 docker exec,别用 docker attach,除非你知道自己在干什么。

  3. 备份迁移:迁移镜像用 docker save / load,做容器快照用 docker export / import,别搞混。

  4. 镜像下载:配国内镜像源,省时间。

  5. 磁盘清理:定期 docker system df 看看,别等磁盘满了才想起来。

Docker 的命令本身不多,常用的就那十几个。真正花时间的,是搞明白每个命令“做了什么”和“没做什么”,还是需要在测试环境,多多地实际上手,踩过坑之后,才能记住和理解这些命令。

感谢您阅读到这里!


评论