apt install docker-ce 跑完并不等于能用了。每次装完新机器我都要重复同样三件事:把当前用户加进 docker 组、给守护进程配代理、然后把服务用 compose 起起来。这篇把这三件事和之后天天要敲的命令一起记下来,下次直接抄。
一、免 sudo 敲 docker
刚装完执行 docker ps 会报 permission denied ... /var/run/docker.sock。因为这个 socket 属于 docker 组,而你的用户不在组里。
# 1. 创建 docker 组(安装时通常已自动创建,执行一下无妨)
sudo groupadd docker
# 2. 将当前用户加入 docker 组
sudo usermod -aG docker $USER
# 3. 激活组更改(或者直接退出并重新登录 SSH)
newgrp docker
newgrp 只对当前这个 shell 生效,新开的窗口仍然是旧的组信息。想彻底干净,还是退出重连 SSH 最省事。
验证:
docker run --rm hello-world
⚠️ 需要知道的一件事:docker 组等价于 root 权限。进了这个组的用户,可以挂载宿主机根目录起一个容器,等于拿到全盘读写。个人服务器无所谓,多人共用的机器就要想清楚再加。
二、给守护进程配代理
在境内拉 docker.io 的镜像经常超时。注意这里要配的是 dockerd 这个守护进程的代理,不是你 shell 里的 http_proxy——因为真正去拉镜像的是后台的 dockerd,它读不到你终端里的环境变量。
正确做法是给 systemd 服务加一个 drop-in 配置。新建目录和文件:
sudo mkdir -p /etc/systemd/system/docker.service.d
/etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:1080"
Environment="HTTPS_PROXY=http://127.0.0.1:1080"
Environment="NO_PROXY=localhost,127.0.0.1,::1,*.local"
端口按自己代理软件的实际监听端口改。加上 NO_PROXY 是为了避免访问本机服务和私有仓库时也绕一圈代理。
改完必须重载并重启:
sudo systemctl daemon-reload && sudo systemctl restart docker
验证有没有生效:
sudo systemctl show --property=Environment docker
或者:
docker info | grep -i proxy
三种代理不要搞混
这里是我当初最容易绕晕的地方,列个表:
| 想让谁走代理 | 配在哪 |
|---|---|
dockerd 拉镜像(docker pull) | /etc/systemd/system/docker.service.d/http-proxy.conf |
| 容器内部的程序联网 | 容器的 -e HTTP_PROXY=...,或 ~/.docker/config.json 的 proxies 段 |
docker build 过程中的联网 | --build-arg HTTP_PROXY=...,或同样走 ~/.docker/config.json |
另外,如果代理跑在宿主机的 127.0.0.1,容器里是连不上的——容器的 127.0.0.1 是它自己。容器里要用宿主机代理,地址得写 host.docker.internal(需要加 --add-host=host.docker.internal:host-gateway)或者宿主机在 docker0 网桥上的 IP(通常是 172.17.0.1)。
三、compose 更新与迁移
改完 docker-compose.yml 或者要同步迁移到新机器,两条命令:
docker compose down
docker compose up -d
想顺带拉最新镜像:
docker compose pull && docker compose up -d
up -d 会自动重建配置有变化的容器,没变化的不动。所以日常改配置其实可以省掉 down,直接 up -d 就够了;down 主要用在要彻底清掉网络和容器的场景。
注意新旧写法:新版是
docker compose(Compose V2,docker 的子命令),老版是docker-compose(独立的二进制)。两者参数基本一致,现在建议一律用前者。
四、常用命令速查
容器生命周期
docker ps # 运行中的容器
docker ps -a # 包括已停止的
docker run -d --name web -p 8080:80 nginx
docker start web
docker stop web
docker restart web
docker rm web # 删除容器(要先 stop,或加 -f)
进容器里看看
docker exec -it web bash # 没有 bash 的精简镜像用 sh
docker logs -f --tail 100 web # 跟踪最近 100 行日志
docker cp web:/etc/nginx/nginx.conf ./ # 从容器拷文件出来
docker cp ./nginx.conf web:/etc/nginx/ # 拷进去
docker logs -f 是我用得最多的一条,容器起不来先看它。
镜像
docker images
docker pull nginx:alpine
docker rmi nginx:alpine
docker tag myapp:latest registry.example.com/myapp:v1
docker push registry.example.com/myapp:v1
排障
docker inspect web # 完整配置,JSON
docker inspect -f '{{ .State.Status }}' web
docker stats # 实时 CPU / 内存占用
docker top web # 容器内进程
docker port web # 端口映射关系
docker events # 实时事件流
清理磁盘
服务器磁盘满了,十有八九是 docker 的悬空镜像和日志。先看占用:
docker system df
再清理:
docker image prune # 清悬空镜像(安全)
docker container prune # 清已停止的容器
docker volume prune # 清没被引用的卷 ⚠️ 会丢数据
docker system prune -a # 全清,包括没有容器在用的镜像 ⚠️
volume prune和system prune -a都是有破坏性的,跑之前先确认没有停着的容器还需要那些卷。
compose 常用
docker compose ps
docker compose logs -f web
docker compose exec web bash
docker compose restart web # 只重启单个服务
docker compose config # 校验 yml 并展开变量
docker compose config 在排查环境变量没生效的问题时很好用,它会把最终展开的结果打印出来。