【Docker】進階之路:(十一)Docker存儲

【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 ~]# 

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/215136.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/215136.shtml
英文地址,請注明出處:http://en.pswp.cn/news/215136.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Jemeter,提取響應體中的數據:正則表達式、Json提取器

一、正則表達式 1、線程組--創建線程組&#xff1b; 2、線程組--添加--取樣器--HTTP請求&#xff1b; 3、Http請求--添加--后置處理器--正則表達式提取器&#xff1b; 4、線程組--添加--監聽器--查看結果樹&#xff1b; 5、線程組--添加--取樣器--調試取樣器。 響應體數據…

docker mysql8 設置不區分大小寫

docker安裝Mysql8.0的坑之lower_case_table_names_docker mysql lower_case_table_names-CSDN博客https://blog.csdn.net/p793049488/article/details/108365929 docker run ‐di ‐‐nametensquare_mysql ‐p 33306:3306 ‐e MYSQL_ROOT_PASSWORD123456 mysql

運籌學經典問題(一):指派問題

問題描述 有 N N N個任務&#xff0c;需要 N N N個人去完成&#xff0c;每個人完成不同工作的效率不同&#xff08;或者資源、收益等等&#xff09;&#xff0c;需要怎么分配使得整體的效率最高&#xff08;成本最低等等&#xff09;呢&#xff1f;這就是經典的指派問題啦&…

金蝶EAS如何增加報表

金蝶EAS如何增加銷售毛利報表&#xff1f; 文章目錄 菜單路徑&#xff1a;導入授權發布管理 菜單路徑&#xff1a; 商業分析———擴展報表中心——報表工具 ——報表工具 汽車 4S——整車管理——整車銷售——擴展報表 導入 選擇報表文件進行導入 授權 發布管理

(純原創)基于JavaWeb的寵物領養商城(詳細源碼以及開發設計報告)

摘要 本寵物領養系統以MVC分層為原則&#xff0c;數據持久化使用Mybatis&#xff0c;數據庫使用MySQL&#xff0c;這些技術目前相對比較成熟&#xff0c;方便系統的維護與擴展 商城系統包括了寵物領養、用戶注冊、用戶登錄、商品查詢、商品添加到購物車、刪除商品等幾大功能…

Linux基礎項目開發2:物聯網監控——視頻監控方案介紹(一)

前言&#xff1a; 這次我們來做一個關于視頻監控的基礎小項目&#xff0c;需要我們用到網絡的相關知識&#xff0c;還會學到好多優秀的網絡協議&#xff0c;下面讓我們開始對物聯網視頻監控進行一個大體框架的介紹吧 目錄 項目內容&#xff1a; 1.視頻監控方案介紹 2.視頻監控…

手寫VUE后臺管理系統10 - 封裝Axios實現異常統一處理

目錄 前后端交互約定安裝創建Axios實例攔截器封裝請求方法業務異常處理 axios 是一個易用、簡潔且高效的http庫 axios 中文文檔&#xff1a;http://www.axios-js.com/zh-cn/docs/ 前后端交互約定 在本項目中&#xff0c;前后端交互統一使用 application/json;charsetUTF-8 的請…

云計算 云原生

一、引言 云計算需要終端把信息上傳到服務器&#xff0c;服務器處理后再返回給終端。在之前人手一臺手機的情況下&#xff0c;云計算還是能handle得過來的。但是隨著物聯網的發展&#xff0c;什么東西都要聯網&#xff0c;那數據可就多了去了&#xff0c;服務器處理不過來&…

汽車標定技術(十二)--A2L文件生成的方法

目錄 1.工具生成 1.1 CANape/ASAP2 Studio 1.2 ASAP2ToolKit 1.3 Matlab/Simulink 2.手寫A2L要點 3.小結 A2L文件的制作一直以來是一個很少有人關注的方向,不管是標定工程師還是Slave協議棧的開

MachMap:End-to-End Vectorized Solution for Compact HD-Map Construction

參考代碼&#xff1a;None 動機與出發點 地平線的MapTR展現出了構建高精地圖的能力&#xff0c;但是它的機制確實是有點復雜了。為了兼容不同車道線的朝向&#xff0c;環形車道線的起終點等情況&#xff0c;針對性設計了permute-equal的匹配邏輯&#xff0c;這樣的邏輯真的是太…

軟件測試之壓力測試詳解

一、什么是壓力測試 軟件測試中&#xff1a;壓力測試&#xff08;Stress Test&#xff09;&#xff0c;也稱為強度測試、負載測試。壓力測試是模擬實際應用的軟硬件環境及用戶使用過程的系統負荷&#xff0c;長時間或超大負荷地運行測試軟件&#xff0c;來測試被測系統的性能、…

leetcode206. 反轉鏈表

題目描述 給你單鏈表的頭節點 head &#xff0c;請你反轉鏈表&#xff0c;并返回反轉后的鏈表。 示例 1&#xff1a; 輸入&#xff1a;head [1,2,3,4,5] 輸出&#xff1a;[5,4,3,2,1]示例 2&#xff1a; 輸入&#xff1a;head [1,2] 輸出&#xff1a;[2,1]示例 3&#xf…

appium安卓app自動化,遇到搜索框無搜索按鈕元素時無法搜索的解決方案

如XX頭條&#xff0c;搜索框后面有“搜索”按鈕&#xff0c;這樣實現搜索操作較為方便。 但有些app沒有設置該搜索按鈕&#xff0c;初學者就要花點時間去學習怎么實現該功能了&#xff0c;如下圖。 這時候如果定位搜索框&#xff0c;再點擊操作&#xff0c;再輸入文本后&#x…

SpringBootWeb請求響應之前言及狀態碼的詳細解析

SpringBootWeb請求響應 前言 在上一次的課程中&#xff0c;我們開發了springbootweb的入門程序。 基于SpringBoot的方式開發一個web應用&#xff0c;瀏覽器發起請求 /hello 后 &#xff0c;給瀏覽器返回字符串 “Hello World ~”。 其實呢&#xff0c;是我們在瀏覽器發起請求…

【算法與數據結構】332、LeetCode重新安排行程

文章目錄 一、題目二、解法三、完整代碼 所有的LeetCode題解索引&#xff0c;可以看這篇文章——【算法和數據結構】LeetCode題解。 一、題目 二、解法 思路分析&#xff1a;本題比較屬于困難題目&#xff0c;難點在于完成機票、出發機場和到達機場之間的映射關系&#xff0c;再…

使用yum/dnf管理軟件包

本章主要介紹使用 yum 對軟件包進行管理。 yum 的介紹搭建yum源創建私有倉庫yum客戶端的配置yum的基本使用使用第三方yum源 使用rpm安裝包時經常會遇到一個問題就是包依賴&#xff0c;如下所示。 [rootrhel03 ~]# rpm -ivh /mnt/AppStream/Packages/httpd-2.4.37-41.modulee…

【三維重建】對極幾何

極幾何描述了同一場景或者物體的兩個視點圖像間的幾何關系 可以發現&#xff30;在左右相機的投影點一定在各自的極線上&#xff0c;如果求出極線就能縮小求解對應點的范圍。 本質矩陣對規范化攝像機拍攝的兩個視點圖像間的極幾何關系進行代數描述 規范化相機指的是相機的內參…

人工智能_機器學習063_SVR支持向量機_回歸擬合天貓雙十一銷量方程---人工智能工作筆記0103

之前我們用線性回歸做過天貓雙十一銷量預測的數據,現在我們再來用SVR支持向量機來做一下 首先上面是給出了銷量,對應2009年到2019年的,銷售額 可以看到: X=np.arange(2009,2020)-2008 統一減去2008的話看起來數據比較簡單了 y=np.array([0.5,9.36,52,191,350,571,912,1207,1…

華為OD機試 - 結隊編程(Java JS Python C)

題目描述 某部門計劃通過結隊編程來進行項目開發, 已知該部門有 N 名員工,每個員工有獨一無二的職級,每三個員工形成一個小組進行結隊編程,結隊分組規則如下: 從部門中選出序號分別為 i、j、k 的3名員工,他們的職級分貝為 level[i],level[j],level[k], 結隊小組滿足…

使用perl的Tie::File 模塊刪除文件固定行

使用perl的Tie::File 模塊刪除文件固定行, 為了說明簡單代碼中處理的是固定第二行開始的3行長度。下面給出perl代碼&#xff1a; #! /usr/bin/perl use v5.14; use Tie::File;if (ARGV 0) {say "請輸入一個文件名 !!!";exit 1; }my $filePath $ARGV[0]; tie my ar…