docker之容器常用命令及基本操作

一、查看容器

ps:该子命令能查看当前正在运行的容器

示例:

[root@localhost ~ ]# docker ps
CONTAINER ID     IMAGE     COMMAND     CREATED      STATUS       PORTS           NAMES
b1a13dfe7105    nginx     "/docker-entrypoint.…"   3 seconds ago    Up 2 seconds        0.0.0.0:32774->80/tcp   reverent_maxwell

字段说明:

  • CONTAINER ID:容器 ID

  • IMAGE:所属镜像

  • COMMAND

  • CREATED:创建时间

  • STATUS:容器状态

  • PORTS:端口

  • NAMES:容器名称

docker ps常用选项

-a: 查看所有容器(包括运行和停止)

docker ps -a

-f:查看停止的容器

docker ps -f status=exited

-q:静默模式,仅显示ID信息

[root@localhost ~ ]# docker ps -aq
b1a13dfe7105

-n:列出最近创建的 n 个容器。

docker ps -n 5

-l : 查看最后一次运行的容器

docker ps -l

inspect

该子命令能够查看该容器详细信息

[root@localhost ~ ]# docker inspect b1a13dfe7105
[
    {
        "Id": "b1a13dfe71056d8c02fb90e52a503bbedc60301f62e9c49604fa86c2258fd310",
        "Created": "2020-12-05T12:18:17.241753416Z",
        "Path": "/docker-entrypoint.sh",
        "Args": [
            "nginx",
            "-g",
            "daemon off;"
        。。。省略行。。。

同样支持 -f 选项过滤指定信息。

[root@localhost ~ ]# docker inspect -f '{{.Id}}' b1a13dfe7105
b1a13dfe71056d8c02fb90e52a503bbedc60301f62e9c49604fa86c2258fd310

二、查看容器日志

  • 格式:docker logs [option] [容器名称或ID]

docker logs命令选项
  • -f:跟踪日志输出。类似tail -f命令。

  • –since:显示某个开始时间的所有日志。

  • -t:显示时间戳。

  • –tail N:仅列出最新N条容器日志。

示例:

[root@localhost ~ ]# docker logs b1a13dfe7105
/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: Getting the checksum of /etc/nginx/conf.d/default.conf

显示时间戳:

[root@localhost ~ ]# docker logs -t b1a13dfe7105
2020-12-05T12:18:17.500960288Z /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
2020-12-05T12:18:17.500995723Z /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
。。。省略行。。。

仅显示三条日志:

# 仅查看3条日志。
[root@localhost ~ ]# docker logs --tail 3 b1a13dfe7105
192.168.112.1 - - [05/Dec/2020:13:46:53 +0000] "GET /favicon.ico HTTP/1.1" 404 153 "http://192.168.112.129:32775/" "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:83.0) Gecko/20100101 Firefox/83.0" "-"
192.168.112.1 - - [05/Dec/2020:13:46:54 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:83.0) Gecko/20100101 Firefox/83.0" "-"
192.168.112.1 - - [05/Dec/2020:13:46:55 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:83.0) Gecko/20100101 Firefox/83.0" "-"

查看2020年12月5日之后的日志:

# 日期格式不能错误。
[root@localhost ~ ]# docker logs --since="2020-12-04" b1a13dfe7105
/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: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
。。。省略行。。。

三、运行容器

docker run能将一个镜像运行为容器。容器当中至少有一个进程运行在前台。

  • 格式:docker run [选项] [镜像名称|镜像ID] [容器启动后内部执行的命令]

docker run 命令常用选项:

-d : 以守护进程的方式运行(在 run 后面加上 -d 参数,则会创建一个守护式容器在后台运行(这样创建容器后不会自动登录容器,如果只加 -i -t 两个参数,创建容器后就会自动进容器里))

-p : 指定端口映射前者是宿主机端口,后者是容器内的映射端口。可以使用多个 -p 做多个端口映射。

# 格式
docker run -p 宿主主机端口:容器向外暴露的端口 [镜像名称:tag | 镜像ID]
docker run -d -p 8899:80 nginx:1.19.2

-P : 随机端口映射,随机使用宿主机的可用端口与容器内暴露的端口映射。

docker run -d -P nginx:1.19.2

–name: 指定容器的名称(为创建的容器命名),同一台宿主主机上的docker名称不能重复。

docker run -d --name 自定义容器名 -P nginx:1.19.2

–rm:当一个容器停止后,就立即删除。

docker run -d --rm nginx:1.19.2

-i : 表示运行容器

-t : 表示容器启动后会进入其命令行。加入这两个参数后,容器创建就能登录进去。即分配一个伪终端;通常和-i连用

# 运行容器后执行bash命令。
docker run -ditP nginx bash

-e : 在容器内设置一个环境变量。

docker run -d -e NGINX_NAME=nginx nginx:1.19.2

–network 指定网络模式,下篇再讲docker网络。

–link:链接到另一个容器。

-h:指定容器内的主机名。

-v: 映射存储卷,可以映射文件及文件夹。表示目录映射关系(前者是宿主机目录,后者是映射到宿主机上的目录),可以使用多个 -v 做多个目录或文件映射。注意:最好做目录映射,在宿主机上做修改,然后共享到容器上;映射后在宿主机文件内的修改都会映射到容器内的文件中。

docker run -d -v 宿主机文件路径:容器内文件路径 nginx:1.19.2

补充

目录挂载(容器数据卷操作)

我们可以在创建容器的时候,将宿主机的目录与容器内的目录进行映射,这样我们就可以通过修改宿主机某个目录的文件从而去影响容器,而且这个操作是双向绑定的,也就是说容器内的操作也会影响到宿主机,实现备份功能。

  但是容器被删除的时候,宿主机的内容并不会被删除。如果多个容器挂载同一个目录,其中一个容器被删除,其他容器的内容也不会受到影响。

  容器与宿主机之间的数据卷属于引用的关系,数据卷是从外界挂载到容器内部中的,所以可以脱离容器的生命周期而独立存在,正是由于数据卷的生命周期并不等同于容器的生命周期,在容器退出或者删除以后,数据卷仍然不会受到影响,数据卷的生命周期会一直持续到没有容器使用它为止。

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

docker run -di -v /mydata/docker_centos/data:/usr/local/data --name centos7-01 centos:7
# 多目录挂载
docker run -di -v /宿主机目录:/容器目录 -v /宿主机目录2:/容器目录2 镜像名

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

匿名挂载

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

# 匿名挂载
docker run -di -v /usr/local/data --name centos7-02 centos:7
# 查看 volume 数据卷信息
docker volume ls

/resources/articles/docker/image-20200813201808718.png

具名挂载

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

# 匿名挂载
docker run -di -v docker_centos_data:/usr/local/data --name centos7-03 centos:7
# 查看 volume 数据卷信息
docker volume ls

/resources/articles/docker/image-20200813202118346.png

指定目录挂载

   一开始给大家讲解的方式就属于指定目录挂载,这种方式的挂载不会在 /var/lib/docker/volume 目录生成内容。

docker run -di -v /mydata/docker_centos/data:/usr/local/data --name centos7-01 centos:7
# 多目录挂载
docker run -di -v /宿主机目录:/容器目录 -v /宿主机目录2:/容器目录2 镜像名
查看目录挂载关系

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

[root@localhost ~]# docker volume inspect docker_centos_data
[
    {
        "CreatedAt": "2020-08-13T20:19:51+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/docker_centos_data/_data",
        "Name": "docker_centos_data",
        "Options": null,
        "Scope": "local"
    }
]
​

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

/resources/articles/docker/image-20200813203856160.png

只读/读写
# 只读。只能通过修改宿主机内容实现对容器的数据管理。
docker run -it -v /宿主机目录:/容器目录:ro 镜像名
# 读写,默认。宿主机和容器可以双向操作数据。
docker run -it -v /宿主机目录:/容器目录:rw 镜像名
volumes-from(继承)
# 容器 centos7-01 指定目录挂载
docker run -di -v /mydata/docker_centos/data:/usr/local/data --name centos7-01 centos:7
# 容器 centos7-04 和 centos7-05 相当于继承 centos7-01 容器的挂载目录
docker run -di --volumes-from centos7-01:ro --name centos7-04 centos:7
docker run -di --volumes-from centos7-01:rw --name centos7-05 centos:7

四、退出容器

  • exit : 容器停止退出

  • Ctrl+P+Q : 容器不停止退出

五、重启容器

当修改了容器内某些配置文件后,可以使用此命令使配置生效

  • 格式:docker restart [容器名称 | 容器ID]

六、启动容器

  • docker start [容器ID / 容器名]

七、停止容器

  • docker stop [容器ID / 容器名]

  • docker stop -f $(docker ps -qa) (所有)

八、强制停止容器

  • docker kill [容器ID / 容器名]

九、刪除已停止的容器

  • docker rm [容器ID]

  • docker rm -f $(docker ps -qa)

十、进入容器

在使用容器的过程中,我们难免需要进入容器进行排查问题。下面来介绍进入容器的四种方式。

1、attach

通过管道,连接容器内PID=1的进程,容器至少有一个进程运行前台。attach 是最早 docker 官方推出的进入容器的命令了,不过使用该命令有一个问题。当多个窗口同时使用该命令进入该容器时,所有的窗口都会同步显示。如果有一个窗口阻塞了,那么其他窗口也无法再进行操作,当所有窗口退出时,容器结束。

  • 格式 :docker attach [容器名或ID]

2.exec(官方推荐使用)

继attach 之后,exec 是官方推出的有一个新的进入容器的命令,这也是目前推荐使用的进入容器的方式。这个命令相当于在容器中执行一个命令。

  • 格式 : docker exec [参数] [容器名或ID] [命令]

示例:

[root@localhost ~ ]# docker exec -it reverent_maxwell sh
用这种方式相当于进入该容器,并且在退出时不会将容器也停止。

3.nsenter

进入容器中,但不进入容器内的进程。Nsenter 是 Linux 提供的命令。需要配合 docker inspect 来使用(早期没有 exec 命令时,企业当中最长用的方式之一),Docker 是用 golang 语言开发,所以它也支持 go 语言的模板语法。

  • 配合 docker inspect 来使用

  • 格式示例:nsenter –target $( docker inspect -f {{.State.Pid}} nginxv1 ) –mount –uts –ipc –net –pid

4、ssh

在镜像(或容器) 中安装 SSH Server,这样就能保证多人进入容器且相互之间不受干扰了,相信大家在当前的生产环境中(没有使用 Docker 的情况)也是这样做的。但是使用了 Docker 容器之后不建议使用 ssh 进入到 Docker 容器内。

  • 在容器里面安装一个 sshd 服务

补充:

创建并进入容器

下面这行命令的意思就是通过镜像 AA 创建一个容器 BB,运行容器并进入容器的 /bin/bash

docker run -it --name 容器名称 镜像名称:标签 /bin/bash

注意:Docker 容器运行必须有一个前台进程, 如果没有前台进程执行,容器认为是空闲状态,就会自动退出。

守护式方式创建容器
docker run -di --name 容器名称 镜像名称:标签
登录守护式容器方式
# 停止容器
docker stop 容器名称|容器ID
# 启动容器
docker start 容器名称|容器ID

十一、复制文件

复制命令类似于 Linux 系统中的 scp 命令,是将宿主主机上的内容上传到容器中,也可能是将容器中的文件下载到宿主主机中。

从容器内复制文件到宿主主机

  • 格式:docker cp [容器ID:容器内文件路径] 宿主主机路径

示例

[root@Stupidkid ~]# docker cp d78575358e04:/usr ./
[root@Stupidkid ~]# ll
总用量 919344
-rw-------.  1 root root      1526 11 13 20:15 anaconda-ks.cfg
-rw-r--r--.  1 root root         0 12  6 19:47 export_nginx.tar
-rw-r--r--.  1 root root      2340 12  6 10:05 pic_spider.py
-rw-r--r--.  1 root root 941396992 12  4 19:40 python3_django.tar
drwxr-xr-x. 10 root root       105 11 17 08:00 usr

从宿主机复制文件到容器

  • 格式 : docker cp 宿主主机路径 [容器ID:容器内文件路径]

  • 示例:

    [root@Stupidkid ~]# docker cp ./export_nginx.tar d78575358e04:/home
    [root@Stupidkid ~]# docker exec d78575358e04 ls /home
    export_nginx.tar
    

删除容器

stop命令仅仅是将容器停止,若要删除容器则使用docker rm子命令。

格式:

docker rm [option] [镜像名称或ID]

rm能删除已停止的容器,对于正在运行的容器可以使用-f选项强制删除,一般不推荐直接将一个正在运行的容器强制删除。

实例:

# 查看正在运行的容器。
[root@localhost ~ ]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
1a9b4ae8766b        nginx               "/docker-entrypoint.…"   About an hour ago   Up About an hour    0.0.0.0:80->80/tcp   pedantic_hopper
# 直接使用rm无法删除。
[root@localhost ~ ]# docker rm 1a9b4ae8766b
Error response from daemon: You cannot remove a running container 1a9b4ae8766b9266f0e5256df1ac56b9647483815f60b447ae9f15d6c3355dec. Stop the container before attempting removal or force remove
# 使用-f选项可以强制删除。
[root@localhost ~ ]# docker rm -f 1a9b4ae8766b
1a9b4ae8766b

使用docker ps -a与rm和stop命令配合,可以达到一个批量处理容器的方式:

# 停止所有正在运行的容器
docker stop $(docker ps)# 删除所有容器,包括正在运行的容器
docker rm -f $(docker ps -a)

十二、查看容器IP地址

我们可以通过以下命令查看容器的元信息。

docker inspect 容器名称|容器ID

也可以直接执行下面的命令直接输出 IP 地址。

docker inspect --format='{{.NetworkSettings.IPAddress}}' 容器名称|容器ID