三、docker基础命令

三、docker基础命令

3.1 镜像相关操作

3.1.1 增加镜像

(1)搜索镜像

(2)拉取镜像

Docker Hub上有大量的高质量的镜像可以用。从Docker镜像仓库获取镜像的命令是docker pull,其命令格式为:

bash 复制代码
docker   pull   [选项]   [Docker Registry地址[:端口号]/]仓库名[:标签]

docker镜像仓库地址:地址的格式一般是<域名/IP>:[端口号],不写的话默认地址是Docker Hub。

仓库名:仓库名是两段式名称,即<用户名>/<软件名>。对于Docker Hub,如果不给出用户名,则默认为library,也就是官方镜像。

一个仓库会包含同一个软件不同版本的镜像, 而标签就常用于对应该软件的各个版本。

bash 复制代码
#根据镜像名称(tag指定版本)拉取镜像  
[root@localhost ~]# docker pull nginx:1.27.2-alpine
1.27.2-alpine: Pulling from library/nginx
43c4264eed91: Pull complete
d1171b13e412: Pull complete
596d53a7de88: Pull complete
f99ac9ba1313: Pull complete
fd072e74e282: Pull complete
379754eea6a7: Pull complete
45eb579d59b2: Pull complete
472934715761: Pull complete
Digest: sha256:2140dad235c130ac861018a4e13a6bc8aea3a35f3a40e20c1b060d51a7efd250
Status: Downloaded newer image for nginx:1.27.2-alpine
docker.io/library/nginx:1.27.2-alpine

alpine 版本:构建容器小镜像的发行版本

(3)导入镜像

bash 复制代码
#假设当前主机有之前提前下载好的镜像文件
[root@localhost dockerimages]# pwd
/dockerimages
[root@localhost dockerimages]# ll
总用量 16856
-rw------- 1 root root 17257984 10月 15 16:55 nginx-1.14-alpine.tar.gz
#可以使用以下命名导入之前旧的镜像【docker image load=docker load】
[root@localhost dockerimages]# docker image load  -i nginx-1.14-alpine.tar.gz
a464c54f93a9: Loading layer  5.796MB/5.796MB
5ac9a5170bf2: Loading layer  11.43MB/11.43MB
b2cbae4b8c15: Loading layer  3.584kB/3.584kB
076c58d2644f: Loading layer  4.608kB/4.608kB
Loaded image: nginx:1.14-alpine
[root@localhost dockerimages]# docker images nginx:1.14-alpine
REPOSITORY   TAG           IMAGE ID       CREATED       SIZE
nginx        1.14-alpine   8a2fb25a19f5   5 years ago   16MB

3.1.2 查看镜像

(1)查看镜像信息

bash 复制代码
#查看所有镜像,也可以使用命令docker image ls -a
[root@localhost dockerimages]# docker images 
REPOSITORY   TAG             IMAGE ID       CREATED        SIZE
nginx        1.27.2-alpine   cb8f91112b6b   12 days ago    47MB
nginx        1.14-alpine     8a2fb25a19f5   5 years ago    16MB
#列表包含了仓库名、标签、镜像ID、创建时间以及所占用的空间。
#其中镜像ID则是镜像的唯一标识,一个镜像可以对应多个标签。
[root@localhost dockerimages]# docker image ls nginx
REPOSITORY   TAG             IMAGE ID       CREATED        SIZE
nginx        1.27.2-alpine   cb8f91112b6b   12 days ago    47MB
nginx        1.14-alpine     8a2fb25a19f5   5 years ago    16MB
[root@localhost dockerimages]# docker image ls nginx:1.14-alpine
REPOSITORY   TAG           IMAGE ID       CREATED       SIZE
nginx        1.14-alpine   8a2fb25a19f5   5 years ago   16MB

镜像体积说明:

这里标识的所占用空间和在Docker Hub上看到的镜像大小不同。Docker Hub中显示的体积是压缩后的体积。在镜像下载和上传过程中镜像是保持着压缩状态的,因此 Docker Hub 所显示的大小是网络传输中更关心的流量大小。 而docker image ls 显示的是镜像下载到本地后展开的大小, 准确说是展开后的各层所占空间的总和, 因为镜像到本地后, 查看空间的时候, 更关心的是本地磁盘空间占用的大小。

另外一个需要注意的问题是, docker image ls 列表中的镜像体积总和并非是所有镜像实际硬盘消耗。 由于 Docker 镜像是多层存储结构, 并且可以继承、 复用, 因此不同镜像可能会因为使用相同的基础镜像, 从而拥有共同的层。 由于 Docker 使用 Union FS, 相同的层只需要保存一份即可, 因此实际镜像硬盘占用空间很可能要比这个列表镜像大小的总和要小的多。

(2)查看镜像的层数

bash 复制代码
[root@localhost dockerimages]# docker history nginx:1.14-alpine
IMAGE          CREATED       CREATED BY                                       SIZE      COMMENT
8a2fb25a19f5   5 years ago   /bin/sh -c #(nop)  CMD ["nginx" "-g" "daemon...   0B
<missing>      5 years ago   /bin/sh -c #(nop)  STOPSIGNAL SIGTERM            0B
<missing>      5 years ago   /bin/sh -c #(nop)  EXPOSE 80                     0B
<missing>      5 years ago   /bin/sh -c #(nop) COPY file:ebf4f0eb33621cc0...   1.09kB
<missing>      5 years ago   /bin/sh -c #(nop) COPY file:4c82b9f10b84c567...   643B
<missing>      5 years ago   /bin/sh -c GPG_KEYS=B0F4253373F8F6F510D42178...   10.5MB
<missing>      5 years ago   /bin/sh -c #(nop)  ENV NGINX_VERSION=1.14.2      0B
<missing>      5 years ago   /bin/sh -c #(nop)  LABEL maintainer=NGINX Do...   0B
<missing>      5 years ago   /bin/sh -c #(nop)  CMD ["/bin/sh"]               0B
<missing>      5 years ago   /bin/sh -c #(nop) ADD file:2e3a37883f56a4a27...   5.53MB
#missing表示这层,或者这个构建步骤在其他的系统上构建的,并且从DockerHub上拉取过来的。

(3)标签为none的镜像

如果查看镜像的显示结果中出现了没有仓库名,也没有标签,均为none的镜像,可能是因为旧的镜像名被转移到了新下载的镜像身上,而旧的镜像上的这个名称则被取消,从而成为了none。除了 docker pull 可能导致这种情况, docker build 也同样可以导致这种现象。 由于新旧镜像同名, 旧镜像名称被取消, 从而出现仓库名、 标签均为 none的镜像。 这类无标签镜像也被称为虚悬镜像 (dangling image) , 可以用下面的命令专门显示这类镜像:

bash 复制代码
[root@localhost ~]# docker image ls -f dangling=true

一般来说, 虚悬镜像已经失去了存在的价值, 是可以随意删除的, 可以用下面的命令删除。

bash 复制代码
[root@localhost ~]# docker image prune

(3)查看镜像详细信息

bash 复制代码
[root@localhost dockerimages]# docker image inspect  nginx:1.27.2-alpine

3.1.3 修改镜像,导出镜像

(1)给镜像重新打标签

bash 复制代码
#拉取nginx:latest镜像并重新打标签
[root@localhost ~]# docker run -it  --rm nginx:latest /bin/bash
root@589428e6a5f6:/# nginx -v
nginx version: nginx/1.27.2
root@589428e6a5f6:/# exit
#重新打标签
[root@localhost ~]# docker tag nginx:latest nginx:1.27.2

(2)导出镜像为文件

  • 可以同时导出多个镜像为一个文件;

  • 指定.tar.gz 可以导出并压缩。

bash 复制代码
#导出镜像,-o:指定导出镜像的位置;
[root@localhost ~]# cd /dockerimages/
[root@localhost dockerimages]# docker image save -o nginx-1.27.2.tar.gz nginx:1.27.2
[root@localhost dockerimages]# ll nginx-1.27.2.tar.gz
-rw------- 1 root root 195826176 10月 16 12:36 nginx-1.27.2.tar.gz

3.1.4 删除镜像

bash 复制代码
#可以通过标签删除镜像
[root@localhost dockerimages]# docker image rm  nginx:latest
Untagged: nginx:latest

#也可以使用ID删除镜像
[root@localhost dockerimages]# docker image ls nginx:1.27.2
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
nginx        1.27.2    7f553e8bbc89   13 days ago   192MB
[root@localhost dockerimages]# docker image rm 7f5
Untagged: nginx:1.27.2
Untagged: nginx@sha256:d2eb56950b84efe34f966a2b92efb1a1a2ea53e7e93b94cdf45a27cf3cd47fc0
Deleted: sha256:7f553e8bbc897571642d836b31eaf6ecbe395d7641c2b24291356ed28f3f2bd0
Deleted: sha256:3ba9e1b5feaec13b6ac4c4039ff77db13d386040a109f2c378707e70a16ceff0
Deleted: sha256:84bde598cdfbb8af5b5509ede416a448ab7b8e38a4b7e5f2808c096739cb10e8
Deleted: sha256:c51526393f89152369e3f34f04409221511ff198968d6e221a7f9f4ed47369c7
Deleted: sha256:9663f01c380b3953165314a61b7f06e064a1ca39914d7bf6bc047f11d2836df8
Deleted: sha256:eb228edcd2ea132c0353513e457bae71a4c06332541ac4517b06f70b71b7e977
Deleted: sha256:b3f70c08ab98515399e812f56f987b033a998abc2fceaa683f432cad5a8bd04a
Deleted: sha256:8d853c8add5d1e7b0aafc4b68a3d9fb8e7a0da27970c2acf831fe63be4a0cd2c

删除时的输出提示:

  • Untagged

镜像的唯一标识是其 ID 和摘要, 而一个镜像可以有多个标签,首先需要做的是将满足我们要求的所有镜像标签都取消,这就是我们看到的 Untagged 的信息。

因为一个镜像可以对应多个标签, 因此当我们删除了所指定的标签后, 可能还有别的标签指向了这个镜像, 如果是这种情况, 那么 Delete 行为就不会发生。 所以并非所有的 docker image rm 都会产生删除镜像的行为, 有可能仅仅是取消了某个标签而已。

  • Deleted

当该镜像所有的标签都被取消了, 该镜像很可能会失去了存在的意义, 因此会触发删除行为。

镜像是多层存储结构, 因此在删除的时候也是从上层向基础层方向依次进行判断删除。

镜像的多层结构让镜像复用变动非常容易, 因此很有可能某个其它镜像正依赖于当前镜像的某一层。 这种情况, 依旧不会触发删除该层的行为。 直到没有任何层依赖当前层时, 才会真实的删除当前层。

除了镜像依赖以外, 还需要注意的是容器对镜像的依赖。 如果有用这个镜像启动的容器存在( 即使容器没有运行), 那么同样不可以删除这个镜像

3.2 容器相关操作

3.2.1 启动容器

Docker运行容器前需要本地存在对应的镜像,如果本地不存在该镜像,Docker会从镜像仓库下载该镜像。容器内的第一个进程必须一直处于运行的状态,否则这个容器,就会处于退出状态!

(1)create,start运行容器------不推荐

bash 复制代码
docker create 镜像名
docker start 容器名
docker  restart 容器名
bash 复制代码
[root@localhost dockerimages]# docker create  nginx:1.27.2-alpine
28cf58a694d09b615e171e705b038fa26a1cc2065e7f4b324e7c3528c4a5563e
[root@localhost dockerimages]# docker ps -a
CONTAINER ID   IMAGE                 COMMAND                   CREATED         STATUS    PORTS     NAMES
28cf58a694d0   nginx:1.27.2-alpine   "/docker-entrypoint...."   2 seconds ago   Created             modest_hawking

#需要使用start启动容器
[root@localhost dockerimages]# docker start 28c
#查看正在运行的容器
[root@localhost dockerimages]# docker ps
CONTAINER ID   IMAGE                 COMMAND                   CREATED          STATUS        PORTS     NAMES
28cf58a694d0   nginx:1.27.2-alpine   "/docker-entrypoint...."   36 seconds ago   Up 1 second   80/tcp    modest_hawking

(2)run运行容器

bash 复制代码
docker run  [OPTIONS]  IMAGE  [COMMAND]  [ARG...]
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

options 常用命令选项

-t :打开一个终端,像使用交换机一样使用容器

-i:交互式访问

--name:容器名字

--network:指定网络

--rm:容器一停,自动删除

-d:后台运行容器,返回容器ID;否则会一直占据着终端

-p:端口映射,将容器内服务的端口映射在宿主机的指定端口,格式为:宿主机端口:容器端口

​ -P: 随机端口映射,容器内部端口随机映射到主机的端口

  • 后台运行容器
bash 复制代码
[root@localhost dockerimages]# docker run --name web1 -d -p 8888:80 nginx:1.14-alpine
427c87d472979472b65a21243437feb71dc0399d44187da441bf845eb5879cb9
#查询docker端口映射
[root@localhost ~]# docker port web1
80/tcp -> 0.0.0.0:8888
80/tcp -> [::]:8888
#启动容器后,dockerd,docker-proxy,containerd,容器中的进程之间的关系
[root@localhost ~]# ps -ef | grep docker
root        1334       1  0 12:02 ?        00:00:18 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
root      194118    1334  0 18:19 ?        00:00:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 8888 -container-ip 172.17.0.2 -container-port 80
root      194124    1334  0 18:19 ?        00:00:00 /usr/bin/docker-proxy -proto tcp -host-ip :: -host-port 8888 -container-ip 172.17.0.2 -container-port 80
root      200158   35149  0 18:34 pts/1    00:00:00 grep --color=auto docker
[root@localhost ~]# ps -ef | grep -v docker |grep container
root         915       1  0 12:02 ?        00:00:08 /usr/bin/containerd
root      194165       1  0 18:19 ?        00:00:00 /usr/bin/containerd-shim-runc-v2 -namespace moby -id 47323e62e9024c75127e13f3851cbbff82a7d1f89c483d769906aafb5a6003aa -address /run/containerd/containerd.sock
root      200776   35149  0 18:36 pts/1    00:00:00 grep --color=auto container
[root@localhost ~]# ps -ef | grep 194165
root      194165       1  0 18:19 ?        00:00:00 /usr/bin/containerd-shim-runc-v2 -namespace moby -id 47323e62e9024c75127e13f3851cbbff82a7d1f89c483d769906aafb5a6003aa -address /run/containerd/containerd.sock
root      194197  194165  0 18:19 ?        00:00:00 nginx: master process nginx -g daemon off;
  • 交互式运行容器
bash 复制代码
[root@localhost dockerimages]# docker run --name busybox1 -it busybox:1.36  /bin/sh
/ # ls
bin    dev    etc    home   lib    lib64  proc   root   sys    tmp    usr    var
#退出容器
/ # exit
  • 查看所有运行和未运行的容器

    bash 复制代码
    #查看所有容器:包括正在运行和已经退出的
    [root@localhost dockerimages]# docker ps -a
    CONTAINER ID   IMAGE                 COMMAND                   CREATED              STATUS                          PORTS                                     NAMES
    475fb18c5356   busybox:1.36          "/bin/sh"                 About a minute ago   Exited (0) About a minute ago                                             busybox1
    427c87d47297   nginx:1.14-alpine     "nginx -g 'daemon of..."   2 minutes ago        Up 2 minutes                    0.0.0.0:8888->80/tcp, [::]:8888->80/tcp   web1
    28cf58a694d0   nginx:1.27.2-alpine   "/docker-entrypoint...."   18 minutes ago       Up 17 minutes                   80/tcp                                    modest_hawking
  • 进入容器运行命令

bash 复制代码
[root@localhost ~]# docker run --name web1 -d -p 8888:80 nginx:1.14-alpine
45c601136fabbdf0f1e3f2c2a6d2bf95c6bb0e6e0f1cb8aa0879ac255ed2a92e
[root@localhost ~]# docker exec -it web1 /bin/sh
/ # cat /etc/hosts
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2      45c601136fab
#容器中的dns默认使用宿主机的dns,可以在运行容器时使用--dns指定别的dns地址
/ # cat /etc/resolv.conf
# Generated by Docker Engine.
# This file can be edited; Docker Engine will not make further changes once it
# has been modified.

nameserver 114.114.114.114
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
47: eth0@if48: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # curl 172.17.0.2:80
/bin/sh: curl: not found
#此时提示没有curl命令,可以使用nsenter进入容器
#查看web1的进程号
[root@localhost ~]#  docker inspect -f {{.State.Pid}} web1
246707
[root@localhost ~]# nsenter -t 246707  -u -i -n
[root@45c601136fab ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
47: eth0@if48: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
[root@45c601136fab ~]# curl -I 172.17.0.2
HTTP/1.1 200 OK

3.2.2 查看容器信息

(1)查看容器信息

bash 复制代码
[root@localhost dockerimages]# docker ps  --help

Usage:  docker ps [OPTIONS]

List containers

Aliases:
  docker container ls, docker container list, docker container ps, docker ps

#查看正在运行的容器
docker ps=docker container ls
#查看所有容器:包括正在运行的和已经停止的
docker ps -a= docker container ls -a
#查看所有容器的id信息
docker ps -a -q
#查看所有已退出容器的id信息
docker ps -aq -f status=exited
bash 复制代码
[root@localhost dockerimages]# docker ps -a
CONTAINER ID   IMAGE                 COMMAND                   CREATED          STATUS                     PORTS                                     NAMES
475fb18c5356   busybox:1.36          "/bin/sh"                 5 minutes ago    Exited (0) 5 minutes ago                                             busybox1
427c87d47297   nginx:1.14-alpine     "nginx -g 'daemon of..."   7 minutes ago    Up 7 minutes               0.0.0.0:8888->80/tcp, [::]:8888->80/tcp   web1
28cf58a694d0   nginx:1.27.2-alpine   "/docker-entrypoint...."   22 minutes ago   Up 21 minutes              80/tcp                                    modest_hawking

(2)查看端口映射信息

bash 复制代码
[root@localhost dockerimages]# docker port --help

Usage:  docker port CONTAINER [PRIVATE_PORT[/PROTO]]

List port mappings or a specific mapping for the container

Aliases:
  docker container port, docker port
bash 复制代码
[root@localhost dockerimages]# docker port web1
80/tcp -> 0.0.0.0:8888
80/tcp -> [::]:8888

(3)查看容器详细信息

bash 复制代码
[root@localhost dockerimages]# docker inspect web1 | grep -i ipaddress
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.3",
                    "IPAddress": "172.17.0.3",

(4)查看容器日志

bash 复制代码
[root@localhost dockerimages]# docker logs -f  web1
172.17.0.1 - - [16/Oct/2024:05:09:40 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.76.1" "-"
192.168.168.101 - - [16/Oct/2024:05:11:13 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.76.1" "-"
172.17.0.1 - - [16/Oct/2024:05:11:42 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.76.1" "-"
#打开另一个终端
[root@localhost ~]# docker port web1
80/tcp -> 0.0.0.0:8888
80/tcp -> [::]:8888
[root@localhost ~]# hostname -I
192.168.168.101 172.17.0.1
#通过容器ip地址访问nginx服务
[root@localhost ~]# curl 172.17.0.3
#通过宿主机ip地址访问容器中的nginx
[root@localhost ~]# curl 192.168.168.101:8888
[root@localhost ~]# curl 172.17.0.1:8888

(5)动态查看容器占用内存和cpu信息

bash 复制代码
[root@localhost ~]# docker stats web1
CONTAINER ID   NAME      CPU %     MEM USAGE / LIMIT     MEM %     NET I/O           BLOCK I/O      PIDS
427c87d47297   web1      0.00%     2.332MiB / 3.532GiB   0.06%     4.84kB / 4.96kB   10MB / 4.1kB   2

(6)查看容器中的进程

bash 复制代码
[root@localhost ~]# docker top web1
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                194197              194165              0                   18:19               ?                   00:00:00            nginx: master process nginx -g daemon off;
100                 194224              194197              0                   18:19               ?                   00:00:00            nginx: worker process

3.2.3 删除容器

bash 复制代码
docker stop 关闭运行的容器
docker kill  杀死运行的容器
		-s:指定信号,和kill 用法一样;-9 强制停止容器
docker rm [-f] 删除容器,可以使用-f强制删除正在运行的容器
docker  container prune #删除所有处于终止状态的容器 
bash 复制代码
#停止容器并删除
[root@localhost ~]# docker ps
CONTAINER ID   IMAGE                 COMMAND                   CREATED          STATUS          PORTS                                     NAMES
427c87d47297   nginx:1.14-alpine     "nginx -g 'daemon of..."   14 minutes ago   Up 14 minutes   0.0.0.0:8888->80/tcp, [::]:8888->80/tcp   web1
28cf58a694d0   nginx:1.27.2-alpine   "/docker-entrypoint...."   29 minutes ago   Up 29 minutes   80/tcp                                    modest_hawking
[root@localhost ~]# docker stop  28c
28c
[root@localhost ~]# docker ps
CONTAINER ID   IMAGE               COMMAND                   CREATED          STATUS          PORTS                                     NAMES
427c87d47297   nginx:1.14-alpine   "nginx -g 'daemon of..."   14 minutes ago   Up 14 minutes   0.0.0.0:8888->80/tcp, [::]:8888->80/tcp   web1
[root@localhost ~]# docker rm 28c

#强制删除正在运行的容器
[root@localhost ~]# docker rm -f web1
web1
[root@localhost ~]# docker ps -a
CONTAINER ID   IMAGE          COMMAND     CREATED          STATUS                      PORTS     NAMES
475fb18c5356   busybox:1.36   "/bin/sh"   14 minutes ago   Exited (0) 14 minutes ago             busybox1

#删除所有已经停止的容器
[root@localhost ~]# docker run busybox:latest
[root@localhost ~]# docker ps -a
CONTAINER ID   IMAGE            COMMAND     CREATED          STATUS                      PORTS     NAMES
89d16c436402   busybox:latest   "sh"        2 seconds ago    Exited (0) 1 second ago               nervous_grothendieck
475fb18c5356   busybox:1.36     "/bin/sh"   16 minutes ago   Exited (0) 16 minutes ago             busybox1
[root@localhost ~]# docker container  prune
[root@localhost ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

3.2.4 管理容器中的数据

如果正在运行中的容器生成了新的数据或者修改了现有的一个已经存在的文件内容,那么新产生的数据将会被复制到读写层进行持久化保存,这个读写层也就是容器的工作目录。这就是"写时复制(COW)copy on write"机制。

容器中修改的数据内容会随着容器的消亡而消失,如果想要将容器中数据永久保存,则需要将容器中的数据保存到宿主机的指定目录中,可以使用如下方式持久化容器数据:

  • 使用docker管理的数据卷

    数据卷的使用, 类似于 Linux 下对目录或文件进行 mount, 镜像中的被指定为挂载点的目录中的文件会隐藏掉, 能看到的是挂载的数据卷里面的内容。

  • 使用宿主机本地的目录作为数据卷

  • 将宿主机的目录挂载至容器,然后让其它容器通过该容器读写宿主机的数据

数据卷的特点:

1、数据卷是宿主机的目录或者文件,并且可以在多个容器之间共同使用。

2、在宿主机对数据卷内容更新后会在所有容器里面立即更新。

3、数据卷的数据可以持久保存,即使删除使用该数据卷的容器也不影响。

4、在容器里面写入的数据不会影响到镜像本身。

(1)运行容器后,数据默认存储位置

bash 复制代码
#运行一个容器
[root@localhost ~]# docker run -d -P --name web2  nginx:1.14-alpine
81227be769c680fe1cafeee75e542637aa1d45f10ad7263cecdcd1e20bd4361d
[root@localhost ~]# docker inspect  web2 | grep -A 5 Data
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/1dee24008f0f138a652daf0c91e91b35875f0de8721acb65c856cd26e6b15b20-init/diff:/var/lib/docker/overlay2/ce2e22e9cb73f2c10206b2932b621c94a1646148bf43a46178043507cc8f2fd6/diff:/var/lib/docker/overlay2/010d7599221a54660d5e422bb2aaab6d46a75c75c92b6aa4383a3f8edbd54765/diff:/var/lib/docker/overlay2/5cd27069ab145ad9b1ee7d3a3edbdb408658401130805f9938e5e2d10641660b/diff:/var/lib/docker/overlay2/c46c1f01ddc4649b06eb400b02d51edc9e9500371d06b739ee37f157d17daf9c/diff",
                "MergedDir": "/var/lib/docker/overlay2/1dee24008f0f138a652daf0c91e91b35875f0de8721acb65c856cd26e6b15b20/merged",
                "UpperDir": "/var/lib/docker/overlay2/1dee24008f0f138a652daf0c91e91b35875f0de8721acb65c856cd26e6b15b20/diff",
                "WorkDir": "/var/lib/docker/overlay2/1dee24008f0f138a652daf0c91e91b35875f0de8721acb65c856cd26e6b15b20/work"
            },

LowerDir:image镜像层(只读)

MergedDir:容器的文件系统,使用Union FS将lowerdir和upperdir合并给容器使用

UpperDir:容器的上层(读写)

WorkDir:容器在宿主机的工作目录,用来存放临时文件

bash 复制代码
#进入容器生成数据
[root@localhost ~]# docker exec -it web2 /bin/sh
/ # echo  this is web2 test > /file
/ # md5sum  /file
008987f269e42d17ffef84111bedb6fe  /file

#查看文件在宿主机的位置,验证宿主机中的文件的md5sum是否和容器中一致
[root@localhost ~]# md5sum /var/lib/docker/overlay2/1dee24008f0f138a652daf0c91e91b35875f0de8721acb65c856cd26e6b15b20/merged/file
008987f269e42d17ffef84111bedb6fe  /var/lib/docker/overlay2/1dee24008f0f138a652daf0c91e91b35875f0de8721acb65c856cd26e6b15b20/merged/file
[root@localhost ~]# md5sum /var/lib/docker/overlay2/1dee24008f0f138a652daf0c91e91b35875f0de8721acb65c856cd26e6b15b20/diff/file
008987f269e42d17ffef84111bedb6fe  /var/lib/docker/overlay2/1dee24008f0f138a652daf0c91e91b35875f0de8721acb65c856cd26e6b15b20/diff/file

删除容器,再看数据文件是否还存在

bash 复制代码
[root@localhost ~]# docker rm -f web2
#容器数据文件随着容器消亡
[root@localhost ~]# ll /var/lib/docker/overlay2/1dee24008f0f138a652daf0c91e91b35875f0de8721acb65c856cd26e6b15b20
ls: 无法访问 '/var/lib/docker/overlay2/1dee24008f0f138a652daf0c91e91b35875f0de8721acb65c856cd26e6b15b20': 没有那个文件或目录

(2)使用数据卷持久化数据

bash 复制代码
[root@localhost ~]# docker volume create my-vol
my-vol
[root@localhost ~]# docker volume ls
DRIVER       VOLUME NAME
local        my-vol

查看指定数据卷的信息

bash 复制代码
#my-vol数据卷在宿主机的实际路径是/var/lib/docker/volumes/my-vol/_data
[root@localhost ~]# docker volume inspect my-vol
[
    {
        "CreatedAt": "2024-10-16T14:59:16+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
        "Name": "my-vol",
        "Options": null,
        "Scope": "local"
    }
]

启动一个挂载数据卷的容器:在用 docker run 命令的时候, 使用 -v 标记来将数据卷挂载到容器里。 在一次docker run 中可以挂载多个数据卷 。

bash 复制代码
#创建一个名为 web2的容器, 并加载一个数据卷到容器的 /usr/share/nginx/html/ 目录 
[root@localhost ~]# docker run -d -P --name web2 -v my-vol:/usr/share/nginx/html nginx:1.14-alpine
[root@localhost ~]# docker ps
CONTAINER ID   IMAGE               COMMAND                   CREATED          STATUS          PORTS                                       NAMES
df628b20139f   nginx:1.14-alpine   "nginx -g 'daemon of..."   16 seconds ago   Up 16 seconds   0.0.0.0:32768->80/tcp, [::]:32768->80/tcp   web2
#删除数据卷会提示不允许删除
[root@localhost ~]# docker volume rm my-vol
Error response from daemon: remove my-vol: volume is in use - [df628b20139ffc652bb60ec5cf06cc850d9203d44ec585977ae1978cf2a5de02]
#在宿主机修改数据卷中文件内容,访问容器时信息会发生变化
[root@localhost ~]# echo web2 > /var/lib/docker/volumes/my-vol/_data/index.html
[root@localhost ~]# curl 192.168.168.101:32768         web2
#进入容器修改文件内容
[root@localhost ~]# docker exec -it web2 /bin/sh
/ # cd /usr/share/nginx/html/
/usr/share/nginx/html # ls
50x.html    index.html
/usr/share/nginx/html # cat index.html
web2
/usr/share/nginx/html # echo web2 container > index.html
/usr/share/nginx/html # exit
#再次访问可以看到信息已经发生变化
[root@localhost ~]# curl 192.168.168.101:32768
web2 container
#删除容器,数据卷仍在
[root@localhost ~]# docker rm -f web2
[root@localhost ~]# ll /var/lib/docker/volumes/my-vol/_data/
总用量 8
-rw-r--r-- 1 root root 537  4月 10  2019 50x.html
-rw-r--r-- 1 root root  15 10月 16 15:06 index.html

数据卷是被设计用来持久化数据的, 它的生命周期独立于容器, Docker不会在容器被删除后自动删除数据卷 。如果需要在删除容器后移除数据卷,可以使用如下命令:

bash 复制代码
[root@localhost ~]# docker volume rm my-vol

由于不存在垃圾回收这样的机制来处理没有任何容器引用的数据卷,无主的数据卷可能会占据很多空间, 所以要清理请使用以下命令:

bash 复制代码
[root@localhost ~]# docker volume prune -af

查看镜像、容器、数据卷所占用的空间

bash 复制代码
[root@localhost ~]# docker system  df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          10        0         444.4MB   444.4MB (100%)
Containers      0         0         0B        0B
Local Volumes   0         0         0B        0B
Build Cache     0         0         0B        0B

(3)在宿主机创建一个目录用来持久化容器数据

bash 复制代码
[root@localhost ~]# mkdir  /docker/data -pv
[root@localhost ~]# docker run -d -P --name web2 -v /docker/data:/usr/share/nginx/html nginx:1.14-alpine
44ca513f2d830a9cbc285ae3b9d3e644ad9dc57e3ca251754f9252b1f0e4a480
[root@localhost ~]# docker ps
CONTAINER ID   IMAGE               COMMAND                   CREATED         STATUS         PORTS                                       NAMES
44ca513f2d83   nginx:1.14-alpine   "nginx -g 'daemon of..."   2 seconds ago   Up 2 seconds   0.0.0.0:32776->80/tcp, [::]:32776->80/tcp   web2
[root@localhost ~]# ll /docker/data/
总用量 0
[root@localhost ~]# curl 192.168.168.101:32776
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.14.2</center>
</body>
</html>
[root@localhost ~]# echo test > /docker/data/index.html
[root@localhost ~]# curl 192.168.168.101:32776
test
#删除容器数据仍在
[root@localhost ~]# docker rm -f web2
web2
[root@localhost ~]# ll /docker/data/
总用量 4
-rw-r--r-- 1 root root 5 10月 16 17:46 index.html
[root@localhost ~]#

(4)通过创建的数据卷容器来读写宿主机的数据

bash 复制代码
#创建数据卷容器
[root@localhost ~]# mkdir /docker/readonly
[root@localhost ~]# echo readonly > /docker/readonly/file
[root@localhost ~]# docker run -d --name web2 -P  -v /docker/readonly:/test:ro -v /docker/data/:/usr/share/nginx/html nginx:1.14-alpine
6622c24035970b8ef42251aa295b47d5c4a20f490f5e74d8a7c84207e7d1b1b0
[root@localhost ~]# docker exec -it web2 /bin/sh
/ # ls /test/
file
/ # echo test >> /test/file
/bin/sh: can't create /test/file: Read-only file system
/ # echo web2 >> /usr/share/nginx/html/index.html
bash 复制代码
#创建容器使用数据卷容器的文件
[root@localhost ~]# docker run -d   --name web2-client1 -P --volumes-from web2 nginx:1.14-alpine
3d8dff4724579028f0f0c72377edd31d801eb6365ca053a0463ae5f2afafa1ad
[root@localhost ~]# docker exec -it web2-client1 /bin/sh
/ # echo test client1 >> /test/file
/bin/sh: can't create /test/file: Read-only file system
/ # echo test client1 >> /usr/share/nginx/html/index.html
#使用宿主机访问web服务
[root@localhost ~]# docker ps
CONTAINER ID   IMAGE               COMMAND                   CREATED              STATUS              PORTS                                       NAMES
3d8dff472457   nginx:1.14-alpine   "nginx -g 'daemon of..."   About a minute ago   Up About a minute   0.0.0.0:32771->80/tcp, [::]:32771->80/tcp   web2-client1
6622c2403597   nginx:1.14-alpine   "nginx -g 'daemon of..."   5 minutes ago        Up 5 minutes        0.0.0.0:32770->80/tcp, [::]:32770->80/tcp   web2
[root@localhost ~]# curl localhost:32770
test
web2
test client1
[root@localhost ~]# curl localhost:32771
test
web2
test client1

#删除web2,web2-client1仍然可以使用该卷
[root@localhost ~]# docker rm -f web2
[root@localhost ~]# docker exec -it web2-client1 /bin/sh
/ # echo client1 >> /usr/share/nginx/html/index.html
[root@localhost ~]# curl localhost:32771
test
web2
test client1
client1
相关推荐
zhj186791306131 小时前
Linux下进程间通信方式 进程间传递文件描述符——sockpair()函数
linux·运维·服务器
xiao-xiang3 小时前
Jenkins-Pipeline简述
运维·jenkins
?-ldl3 小时前
docker使用笔记
笔记·docker·容器
Devil_MayCare3 小时前
Docker配置国内镜像源
docker·容器
xiao-xiang3 小时前
Jenkins-pipeline Jenkinsfile说明
运维·jenkins
里音日黑3 小时前
Elasticsearch 和arkime 安装
linux·运维·服务器·elasticsearch·arkime
Mr.Lee jack5 小时前
【SSH端口转发:实现安全的远程端口映射】
运维·安全·ssh
_.Switch5 小时前
FastAPI 应用的容器化与 Docker 部署:提升性能与可扩展性
数据库·python·网络协议·docker·容器·eureka·fastapi
宅博士小陈5 小时前
实施工程师:面试基础宝典
运维
珀佑勒5 小时前
ubuntu24部署openwrt编译环境
linux·运维·服务器