[Docker] The road to advancement: (11) Docker storage

[Docker] The road to advancement: (11) Docker storage


Docker provides 4 storage methods: default storage, volume (data volume), bind mounts (bind mount), tmpfsmount (only available in Linux environment). Among them, volume and bind mounts are two storage methods to achieve persistent container data. The function of the persistent storage system is to permanently save the data generated by various services during their operation. Even if the container is destroyed, the data will still exist.

Introduction to Docker Storage

Docker provides two resources for storing data for containers, namely the container layer and image layer managed by the storage driver, and the data volume storage volume. In other words, container storage can be divided into two categories: one is related to images, and all files created in the container are stored on the writable container layer. This method of directly storing files on the container layer, Data is difficult to persist and share. This additional abstraction reduces performance due to reliance on storage drivers compared to using data volumes written directly to the host file system; the other is host storage, which is used by binding or mounting the host directory into the container , the data can be persisted even after the container is stopped.

The Docker image is composed of multiple read-only layers. When starting the container, Docker will load the read-only image layer and add a read-write layer on top of the image stack. If a running container modifies an existing file, the file will be copied from the read-only layer below the read-write layer to the read-write layer. The read-only version of the file still exists, but has been read and written. The copy of the file in the layer is hidden, which is the "copy-on-write (COW, Copy-On-Write)" mechanism. For this method, when we access a file, modify and delete operations, etc., the efficiency will be very low because there are many layers of mirrors. To bypass this limitation, we can use the storage volume mechanism.

A data volume directly establishes a binding relationship between a directory that exists in the local file system of the host and a directory on the file system inside the container. This means that when we write data to this directory in the container, the container will write its content directly to the directory on the host that is bound to this container. The directory on the host that is bound to the container is called a data volume.

The advantage of using a data volume is that if all valid data of the process running in the container is saved in the data volume and is separated from the container's own file system, then when the container is closed or even deleted, as long as the data bound to this container is not deleted, , in this storage directory on the host machine, there is no need to worry about data loss. Therefore, the data volume can be separated from the life cycle of the container to achieve persistent data storage.

By managing containers through data volumes, the container can be separated from the constraints of the host. The container can be run on any host where Docker is deployed, and its data can be placed on a shared storage file system, such as an NFS server.

By default, Docker's data volume uses the local file system directory on the host where it is located, which means that the host has its own hard drive. This hard drive is not shared with other Docker hosts, but on this host The data volume used by the container started on the host is associated with a directory on the host's hard disk. This means that if the container stops running on this host or is deleted and then rebuilt, as long as it is associated with this directory on the hard disk, its data will still exist; but if a new container is started on another host, then the data will It’s gone. And if we manually mount the container's data to an NFS server when creating the container, then this problem will be solved.

storage driver

A container consists of a top-level writable container layer and several read-only image layers. The container data is stored in these layers. The characteristics of this layered structure are as follows:

  • New data will be stored directly in the topmost container layer.
  • Modifying existing data will first copy the data from the image layer to the container layer. The modified data is directly saved in the container layer, and the image layer remains unchanged.
  • If there are files with the same name in multiple layers, the user will only see the files in the topmost layer.

The hierarchical structure of images makes the creation, sharing and distribution of images and containers very efficient, all thanks to the Docker storage driver. It is the storage driver that implements the stacking of multiple layers of data and provides users with a single merged unified view. Docker supports a variety of storage drivers, including AUFS, Device Mapper, Btfs, OverlayS, VFs and ZFS. They can both implement layered architecture and have their own characteristics. It is necessary to select the appropriate storage driver based on the actual application scenario. Ubuntu uses AUFS by default, the underlying file system is etfs, and data at each layer is stored in /var/ib/docker/aufs. For stateless application containers, it is a good choice to store data directly in the layer maintained by the storage driver. Stateless means that the container has no data that needs to be persisted and can be created directly from the image at any time.
But for applications that require persistent data, this method is not suitable. When the container starts, it needs to load the existing data, and when the container is destroyed, it wants to retain the new data generated. This is Another storage mechanism of Docker, data volume, is used.

data volume

A data volume (data volume, also called a storage volume) is essentially a directory or file in the host file system and can be directly mounted to the container's file system. The purpose of designing data volumes is to make the persistence of data completely independent of the life cycle of the container, so Docker will not delete its mounted data volume when the container is deleted. A data volume is a special directory available to containers that bypasses the file system and provides many useful features:

  • Data volumes enable data to be shared and reused between containers.
  • Data volumes are directories or files, not unformatted disks.
  • Modifications to the data volume will take effect immediately.
  • Updates to the data volume do not affect the mirror.
  • The data volume will exist until no more containers are in use.

Docker provides four storage methods: default storage, volume (data volume), bind mount (bind mount), and tmpfs mount (only available in Linux environment). Among them, volume and bind mount are two storage methods to achieve persistent container data. .

  • Default storage: The data is saved in the running container. When the container is deleted, the data is also deleted. The default method is for the container to manage its own data. The container file system is actually composed of a series of read-only file layers and the uppermost container writable file layer. The uppermost container writable file layer retains all data and modifications generated during the running of the container. , The management of the writable file layer is implemented using the storage driver of the container (the default is Overlay2, which can be modified through Docker's dameon.json configuration file), and is transparent to the internal file system of the container. Since the container encapsulates a storage driver on top of the file system, its performance is not as good as volume or bind, so it is not recommended to use the default storage method in a production environment.
  • volume: The data is stored in the /var/lib/docker/volumes/ directory of the host file system. This directory is managed by Docker and is not allowed to be modified by other processes. This method is recommended for persisting data.
  • Bind mount: Directly mount any directory or file in the host file system, similar to the shared directory between the host and the container. Any process on the host can access and modify it, and the modification can also be seen in the container. This method is the simplest.
  • tmpfs: Data is temporarily stored in the host memory and will not be written to the file system. After the host is restarted, the data will be deleted.
    Insert image description here

volume

Volume is suitable for use in scenarios where data is shared between multiple containers. When there is no guarantee that the Docker host must have a specified folder or directory structure, using volume can mask these host differences. You can choose to use volumes when you need to store data on a remote host or cloud service, or when you want to back up, restore, or migrate data from one Docker host to another.

Volumes are created and managed by Docker. Data volumes can be created explicitly using the docker volume create command, or when the container is created.

[root@docker ~]# docker volume create nginx_volume
nginx_volume
[root@docker ~]# docker inspect nginx_volume
[
    {
    
    
        "CreatedAt": "2023-12-09T23:42:02+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/nginx_volume/_data",
        "Name": "nginx_volume",
        "Options": null,
        "Scope": "local"
    }
]
[root@docker ~]# 

You can see that the mount point is under Docker’s root directory /var/lib/docker/volumes.
Use the docker volume rm/prune command to clear a single or all unused data volumes. Compared with bind mount, it is an advantage to be able to manage data volumes through docker commands.

[root@docker ~]# docker volume ls
DRIVER    VOLUME NAME
local     f484042048a8c1cb156be0068e554bc81fb65bc6a393ae15a4bad895c2829150
...
local     fd5e826f2d1a0b3e78ff89f0cf3fedf4ed87aceb0feaa8b5c4051ec0ed736dda
local     nginx_volume
[root@docker ~]# docker volume prune
WARNING! This will remove anonymous local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
2990ceb30cd33dd5486d27615e910d43f204311268f3b8f990b787f6486e03dc
...
f484042048a8c1cb156be0068e554bc81fb65bc6a393ae15a4bad895c2829150
8ffd3faac7d6635f8e41b54d8cfcf0a17612a254d1102730038265a8274b823b

Total reclaimed space: 338B
[root@docker ~]# 

When creating a container, if the source of the container mounting is not specified, Docker will automatically create an anonymous data volume, which is also located in the Docker root directory.

[root@docker ~]# docker run -dit -v /usr/share/nginx/html --name nginx_with_volume nginx
4e35c9fa57d097cc23691164f0dcb8a49f31c2919fb09933519c8ecc8b10a2bc
[root@docker ~]# docker volume ls
DRIVER    VOLUME NAME
local     047d04f24e43ce6f7d69221c06cfcd74361cda4ded9e1c133c726d63ae8760e2
local     nginx_volume
[root@docker ~]# ls /var/lib/docker/volumes/
047d04f24e43ce6f7d69221c06cfcd74361cda4ded9e1c133c726d63ae8760e2  metadata.db
backingFsBlockDev                                                 nginx_volume
[root@docker ~]# 

After mounting the data volume, the storage at this time is consistent with bind mount. However, when the Docker host is not guaranteed to have a given directory or file structure, data volumes can help separate the Docker host configuration from the container runtime. In this way, when data needs to be backed up, restored, or migrated from one Docker host to another, the data volume is very convenient and can avoid coupling between the host and the container.
When using bind mounts and data volumes, you need to pay attention to the following propagation coverage principles

  • When binding mounting an empty data volume: the contents of the directory in the container will be propagated (copied) to the data volume.
  • When a non-empty data volume is bind-mounted: the contents of the directory in the container will be overwritten by the data volume or the bound host directory.

Insert image description here

bind mount

Configuration files can be shared between the host and the container through bind mount. For example, save the configuration file of the nginx container on the host machine, and after bind mount, there is no need to enter the container to modify the nginx configuration.
Share code or build output between the host and the container. For example, mount the target directory of a project on the host into a container, so that Maven builds the latest product on the host and can run it directly in the container without generating a new image. The file or directory structure on the Docker host is deterministic.

Note the difference in behavior between bind mount and volume. If an empty volume is mounted to a non-empty container directory, the files in the container directory will be copied to the volume, that is, the original files in the container directory will not be overwritten by the volume. If you use hind mount to mount a host directory to a container directory, the original files in the container directory will be hidden, so only the files in the host directory can be read.

Bind mount has limited functions compared to volume. When using bind mount, a file or directory on the host is mounted into the container. The file or directory is referenced by its full path on the host. The directory does not need to exist on the Docker host, Docker will automatically create it if it does not exist. Note that only directories can be created automatically.

Bind mount a directory /nginx/html into the container through the -v option:

[root@docker ~]# docker run -dt -v /nginx/html:/usr/share/nginx/html --name nginx nginx
66bc659dac18f8dbe4832aabb9a06c47a1eef2004ba51b22dffa1976c1fb078f

View the container Mounts field through docker inspect nginx:

[root@docker ~]# docker inspect nginx
[
    {
    
    
        "Id": "66bc659dac18f8dbe4832aabb9a06c47a1eef2004ba51b22dffa1976c1fb078f",
        "Created": "2023-12-09T15:55:39.145460398Z",
        "Path": "/docker-entrypoint.sh",
        "Args": [
            "nginx",
            "-g",
            "daemon off;"
        ],
        "State": {
    
    
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 10567,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2023-12-09T15:55:39.388333291Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:605c77e624ddb75e6110f997c58876baa13f8754486b461117934b24a9dc3a85",
        "ResolvConfPath": "/var/lib/docker/containers/66bc659dac18f8dbe4832aabb9a06c47a1eef2004ba51b22dffa1976c1fb078f/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/66bc659dac18f8dbe4832aabb9a06c47a1eef2004ba51b22dffa1976c1fb078f/hostname",
        "HostsPath": "/var/lib/docker/containers/66bc659dac18f8dbe4832aabb9a06c47a1eef2004ba51b22dffa1976c1fb078f/hosts",
        "LogPath": "/var/lib/docker/containers/66bc659dac18f8dbe4832aabb9a06c47a1eef2004ba51b22dffa1976c1fb078f/66bc659dac18f8dbe4832aabb9a06c47a1eef2004ba51b22dffa1976c1fb078f-json.log",
        "Name": "/nginx",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "",
        "ExecIDs": null,
        "HostConfig": {
    
    
            "Binds": [
                "/nginx/html:/usr/share/nginx/html"
            ],
            "ContainerIDFile": "",
            "LogConfig": {
    
    
                "Type": "json-file",
                "Config": {
    
    }
            },
            "NetworkMode": "default",
            "PortBindings": {
    
    },
            "RestartPolicy": {
    
    
                "Name": "no",
                "MaximumRetryCount": 0
            },
            "AutoRemove": false,
            "VolumeDriver": "",
            "VolumesFrom": null,
            "ConsoleSize": [
                37,
                108
            ],
            "CapAdd": null,
            "CapDrop": null,
            "CgroupnsMode": "host",
            "Dns": [],
            "DnsOptions": [],
            "DnsSearch": [],
            "ExtraHosts": null,
            "GroupAdd": null,
            "IpcMode": "private",
            "Cgroup": "",
            "Links": null,
            "OomScoreAdj": 0,
            "PidMode": "",
            "Privileged": false,
            "PublishAllPorts": false,
            "ReadonlyRootfs": false,
            "SecurityOpt": null,
            "UTSMode": "",
            "UsernsMode": "",
            "ShmSize": 67108864,
            "Runtime": "runc",
            "Isolation": "",
            "CpuShares": 0,
            "Memory": 0,
            "NanoCpus": 0,
            "CgroupParent": "",
            "BlkioWeight": 0,
            "BlkioWeightDevice": [],
            "BlkioDeviceReadBps": [],
            "BlkioDeviceWriteBps": [],
            "BlkioDeviceReadIOps": [],
            "BlkioDeviceWriteIOps": [],
            "CpuPeriod": 0,
            "CpuQuota": 0,
            "CpuRealtimePeriod": 0,
            "CpuRealtimeRuntime": 0,
            "CpusetCpus": "",
            "CpusetMems": "",
            "Devices": [],
            "DeviceCgroupRules": null,
            "DeviceRequests": null,
            "MemoryReservation": 0,
            "MemorySwap": 0,
            "MemorySwappiness": null,
            "OomKillDisable": false,
            "PidsLimit": null,
            "Ulimits": null,
            "CpuCount": 0,
            "CpuPercent": 0,
            "IOMaximumIOps": 0,
            "IOMaximumBandwidth": 0,
            "MaskedPaths": [
                "/proc/asound",
                "/proc/acpi",
                "/proc/kcore",
                "/proc/keys",
                "/proc/latency_stats",
                "/proc/timer_list",
                "/proc/timer_stats",
                "/proc/sched_debug",
                "/proc/scsi",
                "/sys/firmware",
                "/sys/devices/virtual/powercap"
            ],
            "ReadonlyPaths": [
                "/proc/bus",
                "/proc/fs",
                "/proc/irq",
                "/proc/sys",
                "/proc/sysrq-trigger"
            ]
        },
        "GraphDriver": {
    
    
            "Data": {
    
    
                "LowerDir": "/var/lib/docker/overlay2/ff534546df16bbd82350f99144e242689961bfe3d2965b05ceb747755f6c2b27-init/diff:/var/lib/docker/overlay2/87839d75fc8d8156b6e8e6dce26e33656ac0720f2d38824237b955d1869f4ab5/diff:/var/lib/docker/overlay2/7d21dabb4ec6bd6d9f2539309dd0ca6e73c1ad0ab6b17e04030b3233f57296df/diff:/var/lib/docker/overlay2/5c855af6d6078412b1c70f343d4fdf88630be1c63be7ef4593bb7ccdd016d359/diff:/var/lib/docker/overlay2/29def7eb03e7b3d07c6eba7f6105b42f2526960e257f4e4aa56dfce19be02115/diff:/var/lib/docker/overlay2/9221f66223b31550805df61a409b03861c73bf4de8bfa0df5a56ce30fea53cb4/diff:/var/lib/docker/overlay2/1c494cbe1271bf494d078d9339129ea687e925fef25aca5471dc36bcb4dc2cc4/diff",
                "MergedDir": "/var/lib/docker/overlay2/ff534546df16bbd82350f99144e242689961bfe3d2965b05ceb747755f6c2b27/merged",
                "UpperDir": "/var/lib/docker/overlay2/ff534546df16bbd82350f99144e242689961bfe3d2965b05ceb747755f6c2b27/diff",
                "WorkDir": "/var/lib/docker/overlay2/ff534546df16bbd82350f99144e242689961bfe3d2965b05ceb747755f6c2b27/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [
            {
    
    
                "Type": "bind",
                "Source": "/nginx/html",
                "Destination": "/usr/share/nginx/html",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],
        "Config": {
    
    
            "Hostname": "66bc659dac18",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
    
    
                "80/tcp": {
    
    }
            },
            "Tty": true,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "NGINX_VERSION=1.21.5",
                "NJS_VERSION=0.7.1",
                "PKG_RELEASE=1~bullseye"
            ],
            "Cmd": [
                "nginx",
                "-g",
                "daemon off;"
            ],
            "Image": "nginx",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": [
                "/docker-entrypoint.sh"
            ],
            "OnBuild": null,
            "Labels": {
    
    
                "maintainer": "NGINX Docker Maintainers <[email protected]>"
            },
            "StopSignal": "SIGQUIT"
        },
        "NetworkSettings": {
    
    
            "Bridge": "",
            "SandboxID": "84acc916f76bd8f8d0e1d5a22d944f46a278708b3e5a69980e249e51edd1b6df",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {
    
    
                "80/tcp": null
            },
            "SandboxKey": "/var/run/docker/netns/84acc916f76b",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "97beacc486df02851bfdde8a645f3e2b7472042a42f3fde2db7046a4efcdaff8",
            "Gateway": "172.17.0.1",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.17.0.2",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "MacAddress": "02:42:ac:11:00:02",
            "Networks": {
    
    
                "bridge": {
    
    
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "7a72caeb58cd5c7d7589a06372f8136dd4b0f15e5492d5d7996ef2220423d256",
                    "EndpointID": "97beacc486df02851bfdde8a645f3e2b7472042a42f3fde2db7046a4efcdaff8",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                }
            }
        }
    }
]
[root@docker ~]# 

Next, create an index.html file on the Docker host and write "hello nginx", and then access the container IP. Obviously the mount has taken effect:

[root@docker ~]# echo "hello nginx" > /nginx/html/index.html
[root@docker ~]# curl 172.17.0.2
hello nginx
[root@docker ~]# 

Files can be modified through the Docker host to make the files in the container effective, and vice versa. The container can modify, create, and delete content on the host file system. To deal with this problem, you can configure the permissions of the mounting directory when creating the container, for example, grant read-only permissions:

docker run -dt -v /nginx/html:/usr/share/nginx/html:ro --name nginx nginx

tmpfs mount

The usage scenario of tmpfs mount is: If you do not want to persist data to the container or host due to security or other reasons, you can use tmpfs mount mode: use Liunx to run Docker and avoid writing data to the container storage layer. You can use tmpfs mount,

Tmpfs mout is a non-persistent data storage that only saves data in the host's memory. Once the container stops running, the tmpfs mount will be removed, resulting in total data loss.

You can use tmpfs mount by specifying the –tmpfs parameter or –mount parameter when running the container.

docker run -d \
-it \
--name tmptest \
--mount type=tmpfs,destination=/app \
nginx:latest

docker run -d \
-it \
--name tmptest \
--tmpfs /app \
nginx:latest

cannot specify any other options using the -tmpfsc parameter, and cannot be used for swarm Service.
tmpfs mount has the following two options:

  • tmpfs-size: The number of integers of mounted tmpfs, which is unlimited by default.
  • tmpfs-nide: The file mode of tmpfs, such as 700 or 1700. The default value is 1777, which means any user has write permission.

Use the docker container inspect tmptest command, and then look at the Mounts text part, you can see:

[root@docker ~]# docker container inspect tmptest
[
    {
    
    
        "Id": "0a3a8c958db0663f5ae227c324f761e49698a878c12c3740ea42b474e6e1d814",
        "Created": "2023-12-09T16:08:43.092093398Z",
        "Path": "/docker-entrypoint.sh",
        "Args": [
            "nginx",
            "-g",
            "daemon off;"
        ],
        "State": {
    
    
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 10695,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2023-12-09T16:08:43.363050075Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:605c77e624ddb75e6110f997c58876baa13f8754486b461117934b24a9dc3a85",
        "ResolvConfPath": "/var/lib/docker/containers/0a3a8c958db0663f5ae227c324f761e49698a878c12c3740ea42b474e6e1d814/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/0a3a8c958db0663f5ae227c324f761e49698a878c12c3740ea42b474e6e1d814/hostname",
        "HostsPath": "/var/lib/docker/containers/0a3a8c958db0663f5ae227c324f761e49698a878c12c3740ea42b474e6e1d814/hosts",
        "LogPath": "/var/lib/docker/containers/0a3a8c958db0663f5ae227c324f761e49698a878c12c3740ea42b474e6e1d814/0a3a8c958db0663f5ae227c324f761e49698a878c12c3740ea42b474e6e1d814-json.log",
        "Name": "/tmptest",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "",
        "ExecIDs": null,
        "HostConfig": {
    
    
            "Binds": null,
            "ContainerIDFile": "",
            "LogConfig": {
    
    
                "Type": "json-file",
                "Config": {
    
    }
            },
            "NetworkMode": "default",
            "PortBindings": {
    
    },
            "RestartPolicy": {
    
    
                "Name": "no",
                "MaximumRetryCount": 0
            },
            "AutoRemove": false,
            "VolumeDriver": "",
            "VolumesFrom": null,
            "ConsoleSize": [
                37,
                108
            ],
            "CapAdd": null,
            "CapDrop": null,
            "CgroupnsMode": "host",
            "Dns": [],
            "DnsOptions": [],
            "DnsSearch": [],
            "ExtraHosts": null,
            "GroupAdd": null,
            "IpcMode": "private",
            "Cgroup": "",
            "Links": null,
            "OomScoreAdj": 0,
            "PidMode": "",
            "Privileged": false,
            "PublishAllPorts": false,
            "ReadonlyRootfs": false,
            "SecurityOpt": null,
            "UTSMode": "",
            "UsernsMode": "",
            "ShmSize": 67108864,
            "Runtime": "runc",
            "Isolation": "",
            "CpuShares": 0,
            "Memory": 0,
            "NanoCpus": 0,
            "CgroupParent": "",
            "BlkioWeight": 0,
            "BlkioWeightDevice": [],
            "BlkioDeviceReadBps": [],
            "BlkioDeviceWriteBps": [],
            "BlkioDeviceReadIOps": [],
            "BlkioDeviceWriteIOps": [],
            "CpuPeriod": 0,
            "CpuQuota": 0,
            "CpuRealtimePeriod": 0,
            "CpuRealtimeRuntime": 0,
            "CpusetCpus": "",
            "CpusetMems": "",
            "Devices": [],
            "DeviceCgroupRules": null,
            "DeviceRequests": null,
            "MemoryReservation": 0,
            "MemorySwap": 0,
            "MemorySwappiness": null,
            "OomKillDisable": false,
            "PidsLimit": null,
            "Ulimits": null,
            "CpuCount": 0,
            "CpuPercent": 0,
            "IOMaximumIOps": 0,
            "IOMaximumBandwidth": 0,
            "Mounts": [
                {
    
    
                    "Type": "tmpfs",
                    "Target": "/app"
                }
            ],
            "MaskedPaths": [
                "/proc/asound",
                "/proc/acpi",
                "/proc/kcore",
                "/proc/keys",
                "/proc/latency_stats",
                "/proc/timer_list",
                "/proc/timer_stats",
                "/proc/sched_debug",
                "/proc/scsi",
                "/sys/firmware",
                "/sys/devices/virtual/powercap"
            ],
            "ReadonlyPaths": [
                "/proc/bus",
                "/proc/fs",
                "/proc/irq",
                "/proc/sys",
                "/proc/sysrq-trigger"
            ]
        },
        "GraphDriver": {
    
    
            "Data": {
    
    
                "LowerDir": "/var/lib/docker/overlay2/a36502c882207eccca4aa2d29cae30280016b001e48f46e2d0d44a3cf996bf3f-init/diff:/var/lib/docker/overlay2/87839d75fc8d8156b6e8e6dce26e33656ac0720f2d38824237b955d1869f4ab5/diff:/var/lib/docker/overlay2/7d21dabb4ec6bd6d9f2539309dd0ca6e73c1ad0ab6b17e04030b3233f57296df/diff:/var/lib/docker/overlay2/5c855af6d6078412b1c70f343d4fdf88630be1c63be7ef4593bb7ccdd016d359/diff:/var/lib/docker/overlay2/29def7eb03e7b3d07c6eba7f6105b42f2526960e257f4e4aa56dfce19be02115/diff:/var/lib/docker/overlay2/9221f66223b31550805df61a409b03861c73bf4de8bfa0df5a56ce30fea53cb4/diff:/var/lib/docker/overlay2/1c494cbe1271bf494d078d9339129ea687e925fef25aca5471dc36bcb4dc2cc4/diff",
                "MergedDir": "/var/lib/docker/overlay2/a36502c882207eccca4aa2d29cae30280016b001e48f46e2d0d44a3cf996bf3f/merged",
                "UpperDir": "/var/lib/docker/overlay2/a36502c882207eccca4aa2d29cae30280016b001e48f46e2d0d44a3cf996bf3f/diff",
                "WorkDir": "/var/lib/docker/overlay2/a36502c882207eccca4aa2d29cae30280016b001e48f46e2d0d44a3cf996bf3f/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [
            {
    
    
                "Type": "tmpfs",
                "Source": "",
                "Destination": "/app",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],
        "Config": {
    
    
            "Hostname": "0a3a8c958db0",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
    
    
                "80/tcp": {
    
    }
            },
            "Tty": true,
            "OpenStdin": true,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "NGINX_VERSION=1.21.5",
                "NJS_VERSION=0.7.1",
                "PKG_RELEASE=1~bullseye"
            ],
            "Cmd": [
                "nginx",
                "-g",
                "daemon off;"
            ],
            "Image": "nginx:latest",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": [
                "/docker-entrypoint.sh"
            ],
            "OnBuild": null,
            "Labels": {
    
    
                "maintainer": "NGINX Docker Maintainers <[email protected]>"
            },
            "StopSignal": "SIGQUIT"
        },
        "NetworkSettings": {
    
    
            "Bridge": "",
            "SandboxID": "29b18980d941c359ffad690cd674830496436a15d9554bcf86984f7545352aab",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {
    
    
                "80/tcp": null
            },
            "SandboxKey": "/var/run/docker/netns/29b18980d941",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "15e108b973ba2a69b6ffc457fba78e42940bc075e9b7812d9e85e59be7413e9e",
            "Gateway": "172.17.0.1",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.17.0.3",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "MacAddress": "02:42:ac:11:00:03",
            "Networks": {
    
    
                "bridge": {
    
    
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "7a72caeb58cd5c7d7589a06372f8136dd4b0f15e5492d5d7996ef2220423d256",
                    "EndpointID": "15e108b973ba2a69b6ffc457fba78e42940bc075e9b7812d9e85e59be7413e9e",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.3",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:03",
                    "DriverOpts": null
                }
            }
        }
    }
]
[root@docker ~]# 

おすすめ

転載: blog.csdn.net/sinat_36528886/article/details/134902521
おすすめ