Docker 使用
访问镜像仓库
登录镜像仓库
[root@remote-host ~]# docker login quay.example.com
Username: admin
Password:
WARNING! Your credentials are stored unencrypted in '/root/.docker/config.json'.
Configure a credential helper to remove this warning. See
https://docs.docker.com/go/credential-store/
Login Succeeded
如果是商业的镜像仓库,比方说 Docker 官方的镜像仓库,登陆时不会出现证书问题,但如果是私有化部署的镜像仓库(比如 Quay 或者 Harbor),那么可能会出现 x509 证书问题,错误如下:
[root@remote-host ~]# docker login quay.example.com
Username: admin
Password:
Error response from daemon: Get "https://quay.example.com/v2/": tls: failed to verify certificate: x509: certificate signed by unknown authority
此时有两种方法:
- 手动让 Docker 信任私有仓库的 CA 证书;
- 跳过 TLS 验证。
这两种方法看后边。
信任自定义证书
假设 ca.pem 是自定义的 CA 证书,注意是 CA 证书,不是给私有仓库分发的服务端公钥和私钥。
[root@remote-host ~]# mkdir -p /etc/docker/certs.d/quay.example.com
[root@remote-host ~]# cp ca.pem /etc/docker/certs.d/quay.example.com/
[root@remote-host ~]# systemctl restart docker
[root@remote-host ~]# docker login quay.example.com
Username: admin
Password:
WARNING! Your credentials are stored unencrypted in '/root/.docker/config.json'.
Configure a credential helper to remove this warning. See
https://docs.docker.com/go/credential-store/
Login Succeeded
跳过 TLS 验证
修改配置文件 /etc/docker/daemon.json,添加 insecure-registries 配置:
[root@remote-host ~]# cat /etc/docker/daemon.json
{
"insecure-registries": ["quay.example.com"],
"live-restore": true,
"runtimes": {
"nvidia": {
"args": [],
"path": "nvidia-container-runtime"
}
}
}
[root@remote-host ~]# systemctl restart docker
[root@remote-host ~]# docker info
...output omitted...
Insecure Registries:
quay.example.com
::1/128
127.0.0.0/8
...output omitted...
镜像管理
每个容器镜像的名称都由两部分组成:REPOSITORY 和 TAG,比如 docker.io/library/nginx:1.29.1。
REPOSITORY:就是docker.io/library/nginx表示镜像来自docker.io/library/nginx,是一个 NGINX 镜像TAG:就是1.29.1,标识镜像版本。
[root@remote-host ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx 1.29.1 ad5708199ec7 12 days ago 192MB
nginx latest ad5708199ec7 12 days ago 192MB
如果镜像来自
docker.io/library/,Docker 会自动补全这个仓库前缀,上边查看镜像时只写了nginx,就是因为镜像来自docker.io/library/。如果镜像没有写 TAG,比如只写了
nginx,则 TAG 会自动补全为latest。
拉取镜像
[root@remote-host ~]# docker pull busybox
Using default tag: latest
latest: Pulling from library/busybox
Digest: sha256:f9a104fddb33220ec80fc45a4e606c74aadf1ef7a3832eb0b05be9e90cd61f5f
Status: Image is up to date for busybox:latest
docker.io/library/busybox:latest
列出镜像
[root@remote-host ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
busybox latest 6d3e4188a38a 10 months ago 4.28MB
# 只列出镜像 ID
[root@remote-host ~]# docker images -q
6d3e4188a38a
-q可以只输出镜像 ID,可以配合docker rmi $(docker images -q)批量删除镜像。
查看镜像信息
[root@remote-host ~]# docker inspect busybox
[
{
"Id": "sha256:6d3e4188a38af91b0c1577b9e88c53368926b2fe0e1fb985d6e8a70040520c4d",
"RepoTags": [
"busybox:latest"
],
"RepoDigests": [],
"Parent": "",
"Comment": "",
"Created": "2024-09-26T21:31:42Z",
"DockerVersion": "",
"Author": "",
"Architecture": "amd64",
"Os": "linux",
"Size": 4277910,
"GraphDriver": {
"Data": {
"MergedDir": "/var/lib/docker/overlay2/004c9cec5c6baad88cdb3dd1cdd65f29343d81adb4ff5a088b47fc2d2436fa4f/merged",
"UpperDir": "/var/lib/docker/overlay2/004c9cec5c6baad88cdb3dd1cdd65f29343d81adb4ff5a088b47fc2d2436fa4f/diff",
"WorkDir": "/var/lib/docker/overlay2/004c9cec5c6baad88cdb3dd1cdd65f29343d81adb4ff5a088b47fc2d2436fa4f/work"
},
"Name": "overlay2"
},
...output omitted...
# 也可以用镜像 ID 来查寻
[root@remote-host ~]# docker inspect 6d
镜像重命名
[root@remote-host ~]# docker tag busybox:latest quay.example.com/linux/busybox:v1
上传镜像到私有仓库
[root@remote-host ~]# docker push quay.example.com/linux/busybox:v1
The push refers to repository [quay.example.com/linux/busybox]
65014c70e84b: Pushed
v1: digest: sha256:ec06ff94ef8731492058cbe21bc15fb87ec0b98afc20961955200e7e70203c67 size: 527
删除镜像
[root@remote-host ~]# docker rmi quay.example.com/linux/busybox:v1
Untagged: quay.example.com/linux/busybox:v1
Untagged: quay.example.com/linux/busybox@sha256:ec06ff94ef8731492058cbe21bc15fb87ec0b98afc20961955200e7e70203c67
保存镜像为文件
[root@remote-host ~]# docker save busybox:latest -o busybox.tar.gz
[root@remote-host ~]# file busybox.tar.gz
busybox.tar.gz: POSIX tar archive
通过文件导入镜像
[root@remote-host ~]# docker load -i busybox.tar.gz
65014c70e84b: Loading layer [==================================================>] 4.516MB/4.516MB
Loaded image: busybox:latest
容器的生命周期管理
启动容器
# 前台启动容器
[root@remote-host ~]# docker run --rm -it --name busbox busybox:latest sleep 10
# 后台启动容器
[root@remote-host ~]# docker run --rm -itd --name busbox busybox:latest sh
240bad91a971165de40f69a1fbbf7f71cf4c68721035ec059b682221bba2e2f5
# 设置端口映射,宿主机 8080 映射容器 80
[root@remote-host ~]# docker run --rm -itd -p 8080:80 --name nginx nginx:latest
3b1928b6b02fb2ec1b6cf79fd78e2ddda88e848b891266ef3ed83c5c80e5b036
# 设置目录挂载,本地 /tmp/test 挂载到容器内的 /root/test
[root@remote-host ~]# docker run --rm -itd -v /tmp/test:/root/test --name nginx nginx:latest
43e812fc34775ccf58bfeb938af2f09d186fec88110cafadfc34336ef448c0ae
# 启动容器时设置 DNS
[root@remote-host ~]# docker run -it --dns 8.8.4.4 busybox:latest cat /etc/resolv.conf
# 启动容器时指定网络
[root@remote-host ~]# docker run -it --network test busybox:latest cat /etc/hosts
这里介绍一下部分选项:
| 选项 | 说明 |
|---|---|
-i |
保持容器的 stdin 打开(允许输入) |
-t |
分配一个伪终端(TTY)使输出更“终端友好” |
-d |
在后台启动容器 |
--rm |
容器停止后自动删除 |
-p |
指定端口映射 |
-P |
如果镜像有设置 EXPOSE,则用宿主机随机端口进行映射 |
-v |
设置目录挂载 |
--network |
指定 Docker 网络 |
-i和-t一般是组合使用的,加-it和不加-it的区别就是看执行的命令是否是可交互的。如果命令是非交互式的,加不加区别不大,如果是交互式的,就得加-it了。如果后台启动容器的话一般是
-itd,这样表示容器后台启动,并给容器分配伪终端,不加-it的话容器会因为没有终端而自动退出。
--rm的作用是如果容器停止的话自动删除容器,这样就不需要每次手动清理不需要的容器了。
EXPOSE参考后续的容器镜像构建章节。
列出容器
# 查看正在运行的容器
[root@remote-host ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
240bad91a971 busybox:latest "sh" 16 seconds ago Up 16 seconds busbox
# 查看全部容器
[root@remote-host ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a54fbad90959 busybox:latest "sleep 5" 55 seconds ago Exited (0) 48 seconds ago busbox1
240bad91a971 busybox:latest "sh" About a minute ago Up About a minute busbox
# 只列出镜像 ID
[root@remote-host ~]# docker ps -q
a54fbad90959
240bad91a971
docker ps 命令支持以不同的格式输出,也支持过滤。
以 JSON 格式输出:
[root@remote-host ~]# docker ps --format json
{"Command":"\"sh\"","CreatedAt":"2025-08-02 19:47:55 +0800 CST","ID":"240bad91a971","Image":"busybox:latest","Labels":"","LocalVolumes":"0","Mounts":"","Names":"busbox","Networks":"bridge","Platform":null,"Ports":"","RunningFor":"5 minutes ago","Size":"0B","State":"running","Status":"Up 5 minutes"}
通过 docker ps --filter 可以进行过滤,一下是可选的过滤项(AI 查的,没有全部测试):
| 选项名称 | 含义 |
|---|---|
id |
按容器 ID 过滤(支持前缀匹配) |
name |
按容器名称过滤(支持部分匹配) |
label |
按标签过滤,例如 label=env=prod 或 label=env |
status |
按状态过滤,如 created、running、paused、restarting、exited、dead |
ancestor |
按镜像过滤,可以是镜像名、标签或 ID,例如 ancestor=nginx:latest |
before |
过滤在某容器之前创建的容器(基于容器 ID 或名称) |
since |
过滤在某容器之后创建的容器(基于容器 ID 或名称) |
volume |
挂载了特定卷的容器,例如 volume=mydata |
network |
连接了特定网络的容器,例如 network=frontend |
is-task |
是否是 swarm task(true/false) |
health |
按健康状态过滤(starting、healthy、unhealthy、none) |
publish / expose |
按暴露端口过滤,例如 publish=80(注意:不支持协议) |
[root@remote-host ~]# docker ps --filter status=exit
Error response from daemon: invalid filter 'status=exit': invalid value for state (exit): must be one of created, running, paused, restarting, removing, exited, dead
[root@remote-host ~]# docker ps --filter status=exited
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a54fbad90959 busybox:latest "sleep 5" 6 minutes ago Exited (0) 6 minutes ago busbox1
查询容器详细信息
[root@remote-host ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
67df52d693f6 busybox:latest "sleep 60" 21 seconds ago Up 20 seconds busybox
# 通过容器 ID 查询
[root@remote-host ~]# docker inspect 67d
[
{
"Id": "67df52d693f6913b6d2faa51f0819ef53fd865176e576289c4c5cbad93adf460",
"Created": "2025-08-02T14:56:19.677355266Z",
"Path": "sleep",
"Args": [
"60"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 93201,
"ExitCode": 0,
"Error": "",
"StartedAt": "2025-08-02T14:56:19.772096349Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:6d3e4188a38af91b0c1577b9e88c53368926b2fe0e1fb985d6e8a70040520c4d",
"ResolvConfPath": "/var/lib/docker/containers/67df52d693f6913b6d2faa51f0819ef53fd865176e576289c4c5cbad93adf460/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/67df52d693f6913b6d2faa51f0819ef53fd865176e576289c4c5cbad93adf460/hostname",
"HostsPath": "/var/lib/docker/containers/67df52d693f6913b6d2faa51f0819ef53fd865176e576289c4c5cbad93adf460/hosts",
"LogPath": "/var/lib/docker/containers/67df52d693f6913b6d2faa51f0819ef53fd865176e576289c4c5cbad93adf460/67df52d693f6913b6d2faa51f0819ef53fd865176e576289c4c5cbad93adf460-json.log",
"Name": "/busybox",
...output omitted...
# 通过容器名查询
[root@remote-host ~]# docker inspect busybox
查看端口映射
[root@remote-host ~]# docker port nginx
80/tcp -> 0.0.0.0:8080
80/tcp -> [::]:8080
443/tcp -> 0.0.0.0:8443
443/tcp -> [::]:8443
停止和删除容器
# 查看容器
[root@remote-host ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a54fbad90959 busybox:latest "sleep 5" 55 seconds ago Exited (0) 48 seconds ago busbox1
240bad91a971 busybox:latest "sh" About a minute ago Up About a minute busbox
# 停止容器
[root@remote-host ~]# docker stop busbox
# 删除容器
[root@remote-host ~]# docker rm a54
a54
# 强制删除容器
[root@remote-host ~]# docker rm -f busbox
指定容器的时候既可以通过
docker ps中的NAME指定容器,也可以通过CONTAINER ID,使用CONTAINER ID时,可以只写几个字符串。
docker rm -f可以强制删除,正常是先停止在删除,强制可以跳过停止直接删除。
访问容器
[root@remote-host ~]# docker exec -it nginx id
uid=0(root) gid=0(root) groups=0(root)
[root@remote-host ~]# docker exec -it nginx bash
root@1f773824f719:/#
| 选项 | 说明 |
|---|---|
-i |
保持容器的 stdin 打开(允许输入) |
-t |
分配一个伪终端(TTY)使输出更“终端友好” |
查看容器日志
[root@remote-host ~]# docker logs nginx
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2025/08/29 16:30:23 [notice] 1#1: using the "epoll" event method
2025/08/29 16:30:23 [notice] 1#1: nginx/1.29.1
2025/08/29 16:30:23 [notice] 1#1: built by gcc 12.2.0 (Debian 12.2.0-14+deb12u1)
2025/08/29 16:30:23 [notice] 1#1: OS: Linux 4.18.0-553.69.1.el8_10.x86_64
2025/08/29 16:30:23 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2025/08/29 16:30:23 [notice] 1#1: start worker processes
2025/08/29 16:30:23 [notice] 1#1: start worker process 29
网络管理
创建网络
[root@remote-host ~]# docker network create test
9e75af7c76cd05ff0dddeced30848e4ce88eb177a2883b5d50b379a89fbe31b1
更多的查看
docker network --help。
列出网络
[root@remote-host ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
6ab8c74fbe28 bridge bridge local
835180b30026 host host local
1ba79e362f0d none null local
查看网络信息
[root@remote-host ~]# docker network inspect bridge
[
{
"Name": "bridge",
"Id": "6ab8c74fbe2895558d46b6780b6d40e2d27316e5f1d90b9022be727a2831df60",
"Created": "2025-08-29T20:20:42.119748409+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv4": true,
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
资源清理
# 查看空间占用
[root@remote-host ~]# docker system df -v
Images space usage:
REPOSITORY TAG IMAGE ID CREATED SIZE SHARED SIZE UNIQUE SIZE CONTAINERS
multi-stage v2 bad736cc7077 12 minutes ago 102MB 96.72MB 5.218MB 0
multi-stage v1 45d335032e4c 4 hours ago 102MB 96.72MB 5.218MB 2
registry.access.redhat.com/ubi8/ubi-init 8.10-1756225952 1ebfadf27f58 3 days ago 218MB 198MB 19.53MB 0
registry.access.redhat.com/ubi8/ubi-minimal 8.10-1756195339 086c268d530f 4 days ago 96.7MB 96.72MB 0B 0
registry.access.redhat.com/ubi8/ubi 8.10-1756195303 0ce92d409ef0 4 days ago 198MB 198MB 0B 0
registry.access.redhat.com/ubi8/ubi-micro 8.10-1756195190 cc53cf9d10a2 4 days ago 25.2MB 0B 25.19MB 0
Containers space usage:
CONTAINER ID IMAGE COMMAND LOCAL VOLUMES SIZE CREATED STATUS NAMES
1baac3fe1b9b multi-stage:v1 "/usr/local/nginx/sb…" 1 2B 15 minutes ago Up 15 minutes test
34f6b42322c4 multi-stage:v1 "/usr/local/nginx/sb…" 1 88B 4 hours ago Up 4 hours nginx
Local Volumes space usage:
VOLUME NAME LINKS SIZE
60da63ed72e90e15f9bd012ea1975b18ba043e47765ea019c6dc5048e9b6ce7f 1 510B
2a9cfee796c4ac1c1eba81053c0d329c1d8e4ba6277523fb5d5c1ffc995f89de 0 510B
8f6fe9f6b0238213815c2089b13e62e56f0b2c6ea52aa79607d6755468b6697f 0 510B
65b81e78b9b9e5e663e98049086ee83a929a535b00e8e70d77db87972a67baab 0 510B
af05a58ef56b0164716ce4350b1e07fea4f93b9b92e9d25a39dafb2cb829eb34 1 510B
Build cache usage: 1.285MB
CACHE ID CACHE TYPE SIZE CREATED LAST USED USAGE SHARED
2spqa4lh2m3g* regular 1.28MB 30 seconds ago 0 false
c0obdc51rbrk* regular 1.08kB 35 seconds ago 0 false
qdghyq1dg8tw* regular 0B 30 seconds ago 0 true
x396lkq7ko15* regular 0B 30 seconds ago 0 false
# 删除已停止的容器
[root@remote-host ~]# docker rm `docker ps -aq --filter 'STATUS=exited'`
6695898a2608
c362c17ffca6
#还有另一种写法
[root@remote-host ~]# docker container prune -f
Deleted Containers:
7cd69a2c47b418557e0def81c758b65a0d060cc734a87ea72293ae24fabae9b1
cc73c66e3895c1499237bcf3cf61f01f73af408bb7bf21aaf37f4ea4be97a1cb
Total reclaimed space: 28.58MB
# 清理 72 小时前未被引用的构建缓存
[root@remote-host ~]# docker builder prune --filter "until=72h" -f
ID RECLAIMABLE SIZE LAST ACCESSED
ballh55h0d9ak7yqa1yf6pn63* true 0B 7 minutes ago
rkze2zvufrz0itzinfjdasqzo* true 1.083kB 7 minutes ago
nssejn2xgdzvjyuj4gm7aktty* true 254.3MB 7 minutes ago
rlnkd152duw44w2hmu26f6db3* true 1.284MB 7 minutes ago
r66796hjzserrwuf5rdxc744b true 20B 7 minutes ago
q0peardgxw6fg9mabv87xuy42 true 7.577MB 7 minutes ago
6cyckanymixm9dxqqioww48v7 true 0B 7 minutes ago
Total: 263.1MB
# 清理 72 小时前的全部构建缓存
[root@remote-host ~]# docker builder prune --all --filter "until=72h" -f
ID RECLAIMABLE SIZE LAST ACCESSED
4auxy0fms2nxbmhjh3a0335or* true 0B 28 seconds ago
35z9pd2w9s7a2i410yx401qpu* true 1.083kB 28 seconds ago
m1ari646hm0bdtfcvfbxhu8l4 true 5.218MB 28 seconds ago
wv8w51wi12kia1xbaj7zn3nh4* true 1.284MB 28 seconds ago
k4sd7f93fh9d3mpucbirrzsih true 0B 9 minutes ago
Total: 6.504MB
# 清理悬空/无标签镜像 <none>(不含所有未使用镜像)
[root@remote-host ~]# docker image prune -f
Deleted Images:
deleted: sha256:bad736cc70770ac37a5192e2f45c841e90d567abca1047e19047db090e839f9c
deleted: sha256:5b208024157f6e1c920d121c2f6ed57037a108cac550f5efcd1591c28e8dcb71
Total reclaimed space: 5.218MB