【Docker】進階之路:(十一)Docker存儲
- Docker存儲簡介
- storage driver
- data volume
- volume
- bind mount
- tmpfs mount
Docker提供了4種存儲方式:默認存儲、volume(數據卷)、bind mounts(綁定掛載)、tmpfsmount(僅在Linux環境中提供)。其中volume、bind mounts兩種存儲方式實現持久化容器數據。持久化存儲系統的功能是將各種服務在運行過程中產生的數據長久地保存下來,即使容器被銷毀,數據也仍然存在。
Docker存儲簡介
Docker為容器提供兩種存放數據的資源,分別是由storage driver管理的容器層和鏡像層、data volume存儲卷。也就是說,容器的存儲可以分為兩大類:一種是與鏡像相關的,在容器內創建的所有文件都存儲在可寫容器層上,這種直接將文件存儲在容器層的方式,數據難以持久化和共享。由于依賴存儲驅動與使用直接寫入主機文件系統的數據卷相比,這種額外的抽象會降低性能;另一種是宿主機存儲,即通過將宿主機目錄綁定或掛載到容器中使用,容器停止后數據也能持久化。
Docker鏡像由多個只讀層疊加而成,啟動容器時,Docker會加載只讀鏡像層并在鏡像棧頂部添加一個讀寫層。如果運行中的容器修改了現有的一個已經存在的文件,那么該文件將會從讀寫層下面的只讀層復制到讀寫層,該文件的只讀版本依然存在,只是已經被讀寫層中該文件的副本所隱藏,這就是“寫時復制(COW,Copy-On-Write)”機制。對于這種方式來說,我們去訪問一個文件,修改和刪除等一類的操作,由于隔著很多層鏡像,效率會非常低。而要想繞過這種限制,我們可以通過使用存儲卷的機制來實現。
數據卷就是將宿主機的本地文件系統中存在的某個目錄直接與容器內部的文件系統上的某一目錄建立綁定關系。這就意味著,當我們在容器中的這個目錄下寫入數據時,容器會將其內容直接寫入宿主機上與此容器建立了綁定關系的目錄。在宿主機上與容器形成綁定關系的目錄被稱作數據卷。
使用數據卷的好處是,如果容器中運行的進程的所有有效數據都保存在數據卷中,從而脫離容器自身文件系統之后,那么當容器關閉甚至被刪除時,只要不刪除與此容器綁定的、在宿主機上的這個存儲目錄,就不用擔心數據丟失了。因此,數據卷可以脫離容器的生命周期,實現數據持久化存儲。
通過數據卷的方式管理容器,容器就可以脫離主機的限制,可以在任意一臺部署了Docker的主機上運行容器,而其數據則可以置于一個共享存儲文件系統上,比如NFS服務器。
Docker的數據卷默認情況下使用的是它所在的宿主機上的本地文件系統目錄,也就是說宿主機上有一塊屬于自己的硬盤,這個硬盤并沒有共享給其他的Docker主機,而在這臺主機上啟動的容器所使用的數據卷是關聯到此宿主機硬盤上的某個目錄之下。這就意味著容器在這臺主機上停止運行或者被刪除了再重建,只要關聯到硬盤上的這個目錄下,那么其數據還存在;但如果在另一臺主機上啟動一個新容器,那么數據就沒了。而如果在創建容器的時候,我們手動將容器的數據掛載到一臺NFS服務器上,那么這個問題就解決了。
storage driver
容器由最頂層的可寫容器層以及若干只讀的鏡像層組成,容器的數據就存放在這些層中。這種分層結構的特點如下:
- 新數據會直接存放在最頂層的容器層。
- 修改現有數據會先從鏡像層將數據復制到容器層,修改后的數據直接保存在容器層中,鏡像層保持不變。
- 如果多個層中有名稱相同的文件,那么用戶只能看到最上面那層中的文件。
鏡像的分層結構使得鏡像和容器的創建、共享以及分發變得非常高效,而這些都要歸功于Docker storage driver(存儲驅動)。正是storage driver實現了多層數據的堆疊,并為用戶提供一個單一的合并之后的統一視圖。Docker支持多種storage driver,有AUFS、Device Mapper、Btfs、OverlayS、VFs和ZFS。它們都能實現分層的架構,同時又有各自的特性,需要根據應用的實際場景,選擇合適的storage driver。Ubuntu默認使用AUFS,底層文件系統是etfs,各層數據存放在/var/ib/docker/aufs。對于無狀態的應用容器,直接將數據存放在由storage driver維護的層中是很好的選擇,無狀態意味著容器沒有需要持久化的數據,隨時可以從鏡像中直接創建。
但對于有持久化數據的需求的應用,這種方式就不合適了,容器啟動時需要加載已有的數據,容器銷毀時希望保留產生的新數據,這就要用到Docker的另一種存儲機制data volume。
data volume
data volume(數據卷,也稱為存儲卷)本質上是宿主機文件系統中的目錄或文件,能夠直接被mount到容器的文件系統中。設計數據卷的目的就是讓數據的持久化完全獨立于容器的生命周期,因此Docker不會在容器被刪除時刪除其掛載的數據卷。數據卷是一個可供容器使用的特殊目錄,它可以繞過文件系統提供很多有用的特性:
- 數據卷可以在容器之間共享和重用數據。
- 數據卷是目錄或者文件,而不是沒有格式化的磁盤。
- 對數據卷的修改會立刻生效。
- 對數據卷的更新不會影響鏡像。
- 數據卷會一直存在,直到沒有容器使用為止。
Docker提供四種存儲方式:默認存儲、volume(數據卷)、bind mount(綁定掛載)、tmpfs mount(僅在Linux環境中提供),其中volume、bind mount兩種存儲方式實現持久化容器數據。
- 默認存儲:數據保存在運行的容器中,容器被刪除后,數據也隨之刪除。默認方式是容器管理自己的數據,容器文件系統實際是一系列只讀文件層和最上層的容器可寫文件層組成,最上層的容器可寫文件層保留容器運行過程中產生的所有數據及修改,可寫文件層的管理是利用容器的storage driver實現的(默認是Overlay2,可以通過Docker的dameon.json配置文件修改),對容器內部文件系統是透明的。由于容器在文件系統之上又封裝了一層storage driver,性能比不上volume或bind,因此不建議在生產環境使用默認存儲方式。
- volume:數據存放在主機文件系統/var/lib/docker/volumes/目錄下,該目錄由Docker管理,不允許其他進程修改,推薦該種方式持久化數據。
- bind mount:直接掛載主機文件系統的任何目錄或文件,類似主機和容器的共享目錄,主機上任何進程都可以訪問修改,在容器中也可以看到修改,這種方式最簡單。
- tmpfs:數據暫存在主機內存中,不會寫入文件系統。主機重啟后,數據將被刪除。
volume
volume適合在多個容器間共享數據的場景中使用。當無法確保Docker主機一定擁有某個指定的文件夾或目錄結構時,使用volume可以屏蔽這些宿主機差異。當需要將數據存儲在遠程主機或云服務上,或者是備份、恢復或從一臺Docker主機遷移數據到另一臺Docker主機時,可以選擇使用volume。
volume由Docker創建和管理,可以使用docker volume create命令顯式地創建數據卷,或者在容器創建時創建數據卷。
[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 ~]#
可以看到掛載點處于Docker的根目錄/var/lib/docker/volumes下。
通過docker volume rm/prune命令清除單個或所有未再使用的數據卷。對比綁定掛載bind mount來說,可以通過docker命令來管理數據卷是一個優勢。
[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
8ffd3faac7d6635f8e41b54d8cfcf0a17612a254d1102730038265a8274b823bTotal reclaimed space: 338B
[root@docker ~]#
在創建容器時,如果未指定容器掛載的源,則Docker會自動創建一個匿名數據卷,也是位于Docker根目錄下。
[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 ~]#
當掛載數據卷之后,此時的存儲與bind mount一致。不過當Docker主機不能保證具有給定的目錄或文件結構時,數據卷可協助將Docker主機的配置與容器運行時分離。這樣一來當需要將數據從一臺Docker主機備份、還原或遷移到另一臺主機時,數據卷就很方便了,可以避免主機與容器的耦合。
在使用綁定掛載和數據卷時需要注意以下傳播覆蓋原則
- 綁定掛載一個空數據卷時:容器內目錄的內容會傳播(復制)到數據卷中。
- 綁定掛載非空數據卷時:容器內目錄的內容會被數據卷或綁定的主機目錄覆蓋。
bind mount
通過bind mount可以在宿主機和容器間共享配置文件。例如,將nginx容器的配置文件保存在宿主機上,通過bind mount后就不用進入容器來修改nginx的配置了。
在宿主機和容器間共享代碼或者build輸出。例如,將宿主機某個項目的target目錄掛載到容器中,這樣在宿主機上Maven build一個最新的產品,可以直接在容器中運行,不需要生成一個新的鏡像。Docker主機上的文件或目錄結構是確定的。
注意bind mount和volume行為上的差異。若將一個空volume掛載到一個非空容器目錄上,那這個容器目錄中的文件會被復制到volume中,即容器目錄原有文件不會被volume覆蓋。若使用hind mount將一個宿主機目錄掛載到容器目錄上.那么此容器目錄中原有的文件會被隱藏,從而只能讀取到宿主機目錄下的文件。
bind mount與volume相比功能有限。使用綁定掛載時,主機上的文件或目錄會掛載到容器中.立件或目錄由它在主機上的完整路徑引用。目錄不需要存在于Docker主機上,如果不存在,Docker會自動創建。注意只能自動創建目錄。
通過-v選項綁定掛載一個目錄/nginx/html到容器中:
[root@docker ~]# docker run -dt -v /nginx/html:/usr/share/nginx/html --name nginx nginx
66bc659dac18f8dbe4832aabb9a06c47a1eef2004ba51b22dffa1976c1fb078f
通過docker inspect nginx查看容器Mounts字段:
[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 <docker-maint@nginx.com>"},"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 ~]#
接下來,在Docker主機上創建一個index.html文件并寫入“hello nginx”,然后訪問容器IP,顯然掛載已經生效:
[root@docker ~]# echo "hello nginx" > /nginx/html/index.html
[root@docker ~]# curl 172.17.0.2
hello nginx
[root@docker ~]#
可以通過Docker主機修改文件使容器內文件生效,反過來也可以,容器可以修改、創建和刪除主機文件系統上的內容。處理這個問題時,可以在創建容器的時候配置掛載目錄的權限,例如賦予只讀權限:
docker run -dt -v /nginx/html:/usr/share/nginx/html:ro --name nginx nginx
tmpfs mount
tmpfs mount的使用場景為:若因為安全或其他原因,不希望將數據持久化到容器或宿主機上,則可以使用tmpfs mount模式:使用Liunx運行Docker,避免寫入數據到容器存儲層可以使用tmpfs mount、
tmpfs mout是一種非持久化的數據存儲,僅將數據保存都在宿主機的內存中,一旦容器停止運行tmpfs mount就會被移除,從而總成數據丟失。
可以在運行容器時,通過制定–tmpfs參數或–mount參數來使用tmpfs mount。
docker run -d \
-it \
--name tmptest \
--mount type=tmpfs,destination=/app \
nginx:latestdocker run -d \
-it \
--name tmptest \
--tmpfs /app \
nginx:latest
使用-tmpfsc參數無法指定任何其他的可選項,并且不能用于swarm Service。
tmpfs mount有以下兩個可選項:
- tmpfs-size:掛載的tmpfs的宇節數,默認不受限制。
- tmpfs-nide:tmpfs的文件模式,例如700或者1700,默認值為1777,表示任何用戶都有寫入權限 。
使用docker container inspect tmptest命令,然后查看Mounts文本部分,可以看到:
[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 <docker-maint@nginx.com>"},"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 ~]#