参考

镜像命令

查看镜像(docker images)

1
2
3
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos latest e6a0117ec169 7 months ago 272MB

REPOSITORY:镜像在仓库中的名称
TAG:镜像标签
IMAGE ID:镜像ID
CREATED:镜像创建日期(不是获取该镜像的日期)
SIZE:镜像大小

从网络中找出需要的镜像

1
2
3
4
5
6
7
8
[root@localhost ~]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 11997 [OK]
mariadb MariaDB Server is a high performing open sou… 4595 [OK]
mysql/mysql-server Optimized MySQL Server Docker images. Create… 899 [OK]

# 可选项,通过搜索来过滤
--filter = STARS = 3000 搜索出的镜像是STARS>3000的

NAME:镜像名称
DESCRIPTION:镜像描述
STARS:用户评价(受欢迎的程度)
OFFICIAL:是否为官方构建
AUTOMATED:自动构建,表示该镜像是由 Docker Hub 自动构建流程创建的

拉取镜像(docker pull)

拉取镜像就是从中央仓管总下载镜像到本地

如果不声明Tag镜像标签信息则默认拉取latest版本,通过https://hub.docker.com搜索镜像,可以查看支持的Tag信息。

1
docker pull centos  # 相当于 docker pull centos:latest

通过Tag信息,下载centos_20.04的镜像

1
docker pull centos:20.04

删除镜像(docker rmi)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 删除单个镜像
docker rmi 镜像ID

# 删除多个镜像
docker rmi [镜像ID] [镜像ID] [镜像ID]

docker images -q 可以查询到所有镜像的 ID,通过组合命令可以实现删除所有镜像的操作。
docker rmi `docker images -q`
或者
docker rmi $(docker images -aq)

# 删除没用的镜像,按需更改关键字test
docker images|grep none|awk '{print $3}'|xargs docker rmi
docker images|grep test|awk '{print $3}'|xargs docker rmi

# 清除没有用到的数据卷,有重要数据要谨慎
docker volume prune
# 删除 dangling volmue
docker volume rm $(docker volume ls -qf dangling=true)

注意:如果通过了某个镜像创建了容器,则该镜像无法删除。

解决办法:先删除镜像中的容器,在删除该镜像,或者使用-f强制删除

提交镜像(docker commit)

将已有容器创建为一个新的镜像,包含容器的所有层,包含原来的一些设置,如端口、环境变量等 比较臃肿,主要用来备份容器。

1
docker commit [可选参数] [容器名|容器ID]:[Tag] [新的镜像名]

参数说明:
-a:提交的镜像作者
-c:使用Dockerfile指令来创建镜像
-m:提交时的说明文字
-p:在commit时,将容器暂停

导出镜像(docker save)

将指定镜像保存成tar归档文件

1
2
3
docker save [可选参数] [tar归档文件] [容器名|容器ID]:[Tag]
# >可指定目录
docker save [可选参数] [容器名|容器ID]:[Tag] > [tar归档文件]

可选参数:
-o :–output 保存到文件,默认为标准输出STDOUT

1
2
3
4
5
6
7
# 导出镜像,支持同时导出多个镜像,如果没有指定tag,则默认保存所有tag,而非latest
docker save -o images.tar image1:tag [image2:tag ...]
# 导出镜像并压缩
docker save nginx:1.20.1 | gzip > nginx_1.20.1.tar.gz
# 打包所有镜像,两条命令等同
docker save $(docker images --format "{{.Repository}}:{{.Tag}}" |tr '\n' ' ') -o k8s-images.tar
docker save $(docker images | grep -v REPOSITORY | awk 'BEGIN{OFS=":";ORS=" "}{print $1,$2}') -o k8s-images.tar

载入镜像(docker load)

通过save导出和load导入的镜像信息应该是完全一致的才对,如tag和images id都是一致的,否则报错。

1
2
3
4
5
6
7
8
9
10
# 导入镜像
docker load -i images.tar
# 导入压缩的镜像包
gunzip -c nginx_1.20.1.tar.gz | docker load
# 或者解压后再导入
tar -zxf nginx_1.20.1.tar.gz
docker load -i nginx_1.20.1.tar
# 打包指定前缀的镜像,两条命令等同
docker save $(docker images --format "{{.Repository}}:{{.Tag}}" rancher/* |tr '\n' ' ') -o rancher-images.tar
docker save $(docker images rancher/* | grep -v REPOSITORY | awk 'BEGIN{OFS=":";ORS=" "}{print $1,$2}') -o rancher-images.tar

推送镜像(docker push)

Docker Hub

  1. 注册
  2. 登录
    通过执行docker login命令交互式的输入用户名及密码来完成在命令行界面登录 Docker Hub。
    1
    docker login
    通过docker logout退出登录。
  3. 新建Tag
    1
    2
    3
    4
    5
    # 查看镜像列表
    $ docker images
    ubuntu:18.04 8.0.11 5dbe5b6313e1 2 years ago 445MB
    # 打上Tag,username替换为自己的,这步不能跳过
    docker tag 5dbe5b6313e1 username/ubuntu:18.04
  4. 推送
    1
    docker push username/ubuntu:18.04
  5. 查看
    1
    2
    3
    $ docker search username
    NAME DESCRIPTION STARS OFFICIAL AUTOMATED
    username/ubuntu
    注意:推送完成的镜像可能需要几个小时才能被搜索到

ghcr.io

GitHub 镜像仓库服务(ghcr.io)

  1. Github创建登陆 Token
    Github Container registry 需要使用 https://github.com/settings/tokens/new 页面创建的 Token 作为密码才可以推送镜像。
    打开上面的链接,勾选 write:packages 和 read:packages ,repo 会自动选中,创建 Token。

下面以$PAT代指这里的Token值。

  1. 登陆
    1
    echo $PAT | docker login ghcr.io --username username --password-stdin
  2. 新建Tag
    1
    2
    3
    4
    5
    # 查看镜像列表
    $ docker images
    mysql 8.0.11 5dbe5b6313e1 2 years ago 445MB
    # 打上Tag
    docker tag 5dbe5b6313e1 ghcr.io/username/app:1.0.0
  3. 推送
    1
    docker push ghcr.io/username/app:1.0.0

推送完成镜像之后,在github个人的主页packages标签页下面,可以看到镜像列表。

构建镜像(Dockerfile)

Dockerfile是用来构建Docker镜像的一种脚本语言,它记录了构建这个镜像的步骤和过程,以及构建出来的镜像所包含的文件系统、指令和配置等信息。

Dockerfile的使用非常简单,只需要在一个文本文件中编写所需的指令,并将其保存为Dockerfile,在最顶层文件夹中构建出Docker镜像。

基本语法:
.dockerignore文件的写法和.gitignore类似,支持正则和通配符,具体规则如下:

  • 每行为一个条目;
  • #开头的行为注释;
  • 空行被忽略;
  • 构建上下文路径为所有文件的根路径;
  • 文件匹配规则具体语法如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    # comment
    */temp* # 匹配根路径下一级目录下所有以 temp 开头的文件或目录
    */*/temp* # 匹配根路径下两级目录下所有以 temp 开头的文件或目录
    temp? # 匹配根路径下以 temp 开头,任意一个字符结尾的文件或目录
    **/*.go # 匹配所有路径下以 .go 结尾的文件或目录,即递归搜索所有路径

    # 匹配根路径下所有以 .md 结尾的文件或目录,但 README.md 除外
    *.md
    !README.md

下面是几个常用的Dockerfile指令:

FROM:指定该镜像的基础镜像。
MAINTAINER:指定该镜像的作者信息。
RUN:在当前镜像上运行指令。
COPY:将宿主机上的文件复制到镜像中。
ADD:将宿主机上的文件或URL添加到镜像中。
CMD:指定容器启动时运行的指令。
ENTRYPOINT:指定容器启动时运行的可执行文件。
ENV:设置环境变量。
ARG:定义构建时的参数。
WORKDIR:指定工作目录。
EXPOSE:暴露容器的端口号。

编写好Dockerfile后,我们可以使用docker build命令来构建这个镜像,例如:

1
docker build -t myimage:1.0 .

其中,-t指定了该镜像的名称和标签,后面的myimage:1.0就是镜像的名称和标签,最后的.表示Dockerfile所在的目录。

接着,使用docker run命令来启动这个镜像创建的容器,例如:

1
docker run -it myimage:1.0 /bin/bash

其中,-it表示使用交互式终端,并进入容器的bash shell。myimage:1.0就是刚刚构建的镜像的名称和标签。

易混淆的dockerfile命令

COPY 和 ADD

  • ADD:拷贝文件或目录到容器中,如果是URL或压缩包便会自动下载或自动解压
  • COPY:拷贝文件或目录到容器中,跟ADD类似,但不具备自动下载或解压的功能

ENTRYPOINT 和 CMD

  • ENTRYPOINT:运行容器时执行的shell命令
  • CMD:运行容器时提供默认值。这些默认值可以是可执行文件,也可以省略可执行文件,省略可执行文件时必须用ENTRYPOINT为指令提供默认参数(Exec 格式);如果有多个则只有最后一个生效

ENV 和 ARG

  • ENV:容器环境变量
  • ARG:只作用于 Dockerfile 内部的环境变量

容器命令

查看容器信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 查看正在运行的容器并带出历史运行过的容器
docker ps -a
# 只显示容器ID
docker ps -q
# 查看所有容器(包括运行和停止)
docker ps -f startus=exited
# 查看最后一次运行的容器
docker ps -l
# 列出最近创建的 n 个容器
docker ps -n 3

# 查看容器元信息
docker inspect [容器名称|容器ID]

# 筛选查看IP地址
docker inspect --format='{{.NetworkSettings.IPAddress}}' [容器名|容器ID]

# 查看容器cpu占用
docker stats

# 查看容器内部的进程
docker top [容器ID]

创建容器(docker run)

语法

1
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

其中,OPTIONS表示各种启动参数;IMAGE表示要运行的Docker镜像名称或ID;COMMAND表示镜像启动后要运行的命令,通常是一个可执行文件或脚本;ARG…表示命令的参数。

下面是一些常用的docker run命令参数:

-it: 以交互式的方式启动容器,并分配一个伪终端。
--name <name>: 为容器指定一个名称。
--rm: 当容器退出时自动删除容器。
--net <network>: 指定容器所属的网络,–net参数的常用取值包括:

  • bridge: 表示使用默认的docker0网桥,容器可以通过主机的IP地址进行访问,但不能访问其他容器。
  • host: 表示容器与主机共享同一个网络命名空间,容器可以通过主机的IP地址直接访问主机网络资源。
  • overlay: 表示创建一个跨主机网络。
  • none: 表示不使用任何网络,容器只拥有localhost地址。
    --restart: 用于设置Docker容器的自动重启策略,–restart参数的可选值包括:
  • no: 不自动重启容器。
  • on-failure[:max-retries]: 在容器发生错误时自动重启,并可配置最大重试次数。
  • always: 总是重启容器,包括容器正常停止和异常停止。
  • unless-stopped: 在容器停止时自动重启,但不包括人工停止容器。
    -p <host port>:<container port>: 将主机端口映射到容器内的端口。例如,-p 8080:80表示将主机的8080端口映射到容器内的80端口。
    -v <host path>:<container path>: 将主机的文件或目录挂载到容器内的目录。
    -c <command>: 用于指定在容器内执行的命令,若命令执行失败容器会立即停止,-c "echo hello world":执行命令需要加引号,执行脚本不需要,如-c /bt.sh
    --entrypoint <command>: 指定容器的启动命令。
    --privileged=true: 给容器分配特权模式。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$ docker run --name test -it debian
$ docker run -it --rm ubuntu bash
$ docker run -it --privileged ubuntu bash
$ docker run -w /path/to/dir/ -it ubuntu pwd
# 挂载本地目录到容器,并指定容器的工作目录
$ docker run -v /doesnot/exist:/foo -w /foo -it ubuntu bash
# 只读挂载
$ docker run --read-only -v /icanwrite busybox touch /icanwrite/here
$ docker run -p 127.0.0.1:80:8080/tcp ubuntu bash
$ docker run --expose 80 ubuntu bash
# 指定容器环境变量
$ docker run -e MYVAR1 --env MYVAR2=foo --env-file env.list ubuntu bash
$ docker run --env VAR1=value1 --env VAR2=value2 ubuntu env | grep VAR
$ docker run --env-file env.list ubuntu env | grep VAR
# 指定容器标签
$ docker run -l my-label --label com.example.foo=bar ubuntu bash
$ docker run --label-file labels ubuntu bash
$ docker run -itd --network=my-net busybox
$ docker run --volumes-from 777f7dc92da7 --volumes-from ba8c0c54f0f2:ro -it ubuntu pwd
$ docker run -it --rm --gpus all ubuntu nvidia-smi
$ docker run --restart=always redis
# 指定hosts记录
$ docker run --add-host=docker:192.168.10.10 --rm -it alpine

# 通过host模式运行宝塔镜像,自动映射宝塔面板全端口到外网
$ docker run -tid --name baota --net=host --privileged=true --shm-size=1g --restart always -v ~/wwwroot:/www/wwwroot pch18/baota

进入与退出容器

1
2
3
4
5
6
7
8
# 进入容器后开启一个新的终端
docker exec -it [容器名称|容器ID] /bin/bash
# 进入一个容器正在执行的终端
docker attach [容器名称|容器ID]
# 退出当前容器
exit
# 容器不停止退出
Ctrl+P+Q

停止与启动容器

1
2
3
4
5
6
7
8
9
10
11
# 启动容器
docker start 容器ID
# 重启容器
docker restart 容器ID
# 停止当前容器
docker stop 容器ID
# 强制停止容器
docker kill 容器ID
# 停止所有容器,两条命令等同
docker stop $(docker ps -aq)
docker ps -aq |xargs docker stop

删除容器(docker rm)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 删除指定的容器,不能删除正在运行的容器,强制删除rm -f
docker rm [容器名称|容器ID]
# 删除所有容器,两条命令等同
docker rm $(docker ps -q)
docker ps -aq |xargs docker rm
# 删除所有关闭的容器
docker rm $(docker ps -aq -f status=exited)
# 删除异常状态容器
docker ps -a |grep Exited | awk '{print $1}'|xargs docker rm
docker ps -a |grep Created | awk '{print $1}'|xargs docker rm

# 清除没有用到的数据卷,有重要数据要谨慎
docker volume prune
# 删除 dangling volmue
docker volume rm $(docker volume ls -qf dangling=true)

导出容器(docker export)

导出Docker容器的文件系统(类似于安卓里的system分区)到本地,但不包含Docker镜像、容器的元数据(比如启动脚本、环境变量等)等,因此导出后的文件无法直接用于创建新的镜像或者启动容器,一般被用于将容器的文件系统迁移到其他系统中去

1
2
3
4
# 导出容器,只能导出单个容器
docker export -o container1.tar container1
# 使用 gzip 压缩,大幅减小容器体积
docker save container1 | gzip > container1.tar.gz

导入容器(docker import)

1
2
# 导入容器
docker import container1.tar [新容器名]

文件拷贝(docker cp)

将文件拷贝到容器内

1
docker cp [需要拷贝的文件或目录] [容器名称:容器目录]

将文件从容器内拷贝出来

1
docker cp [容器名称:容器目录] [需要拷贝的文件或目录]

目录挂载(-v)

​目录挂载是属于容器数据卷操作,我们可以在创建容器的时候,将宿主机的目录与容器内的目录进行映射,从而创建一个共享目录
文件共享,但是容器被删除的时候,宿主机的内容并不会被删除,如果多个容器挂载同一个目录,其中一个容器被删除,其他容器的内容也不会受到影响。

创建容器时添加-v参数,格式为-v [宿主机目录]:[容器目录], 例如:

1
2
3
docker run -id -v /mydata/docker_centos/data:/usr/local/data --name centos01 centos:7
# 多个目录挂载
docker run -id -v 宿主机目录1:容器目录1 -v 宿主机目录2:容器目录2 --name 容器名 镜像名

在挂载时有可能会出现权限不足的提示。这是因为 CentOS7 中的安全模块 SELinux 把权限禁掉了,在docker run时通过-privileged=true给该容器加权限来解决挂载的目录没有权限的问题

匿名挂载

1
docker run -id -v /usr/local/data --name centos02 centos:7

匿名挂载只需要写容器目录即可,容器外对应的目录会在/var/lib/docker/volumes中生成。

查看 volume 数据卷信息

1
2
$ docker volume ls
image-20220331113929297

具名挂载

具名挂载就是给数据卷取个名字,容器外对应的目录就会在/var/lib/docker/volume中生成。

1
docker run -id -v docker_centos_data:/usr/local/data --name centos03 centos:7

指定目录挂载

最开始的挂载就是指定目录挂载,这种方式的挂载不会在/var/lib/docker/volume目录生成内容。

1
docker run -id -v /mydata/docker_centos/data:/usr/local/data --name centos01 centos:7

查看目录挂载关系

通过docker volue inspect [数据卷名称]可以查看该数据卷对应宿主机目录地址。

1
2
3
4
5
6
7
8
9
10
11
12
[root@localhost ~]# docker volume inspect centos_data
[
{
"CreatedAt": "2022-03-30T20:40:07-07:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/centos_data/_data",
"Name": "centos_data",
"Options": null,
"Scope": "local"
}
]

通过docker inspect [容器ID或名称],在返回的JSON节点中找到Mounts, 可以查看详细数据挂载信息。

只读只写

只读:只能通过修改宿主机内容实现对容器的数据管理

1
docker run -it -v [宿主机目录]:[容器目录]:ro --name [容器名] [镜像名]:[标签]

只写:默认,宿主机和容器可以双向操作数据

1
docker run -it -v [宿主机目录]:[容器目录]:rw --name [容器名] [镜像名]:[标签]

继承(volumes-from)

也就是将其他一个或多个容器继承于某一个容器的挂载目录

1
2
3
4
5
# 容器 centos7-01 指定目录挂载
docker run -id -v /mydata/data:/usr/local/data --name centos7-01 centos:7
# 容器 centos7-02 和 centos7-03 相当于继承 centos7-01 容器的挂载目录、
docker run -id --volumes-from centos7-01:ro --name centos7-04 centos:7 # 只读
docker run -id --volumes-from centos7-01:rw --name centos7-05 centos:7 # 双向(默认)

其它命令

帮助命令

1
docker [命令] --help

查看日志

1
docker -f -t --tail
  • -f:显示日志
  • -t:带上时间戳
  • --tail:显示多少条日志

显示docker的版本信息

1
docker version

显示docker的系统信息

镜像和容器的数量等

1
docker info

彻底删除未使用的容器和镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 36 21 7.412GB 3.798GB (51%)
Containers 69 35 460.8MB 460.4MB (99%)
Local Volumes 8 8 141.8MB 0B (0%)
Build Cache 0 0 0B 0B
$ docker ps -a | grep Exited | wc -l
33
$ docker ps | wc -l
36
$ docker images | wc -l
38
$ docker container prune
$ docker image prune
$ docker system prune
WARNING! This will remove:
- all stopped containers
- all networks not used by at least one container
- all dangling images
- all dangling build cache
$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 36 17 7.412GB 5.204GB (70%)
Containers 36 35 354.6kB 0B (0%)
Local Volumes 8 5 141.8MB 771.3kB (0%)
Build Cache 0 0 0B 0B