容器在運行的過程中,難免會涉及到文件的讀寫,比如web服務器讀取靜態文件,記錄訪問日志和錯誤日志,設定網站根目錄以及目錄權限,還有多個容器之間共享數據等等。
Docker在容器中管理數據主要有兩種方式:
數據卷(Data Volumes):容器內數據直接映射到宿主機
數據卷容器(Data Volume Containers):使用特定容器來管理數據
在使用docker run 命令時,可以使用-v 參數來把主機的目錄映射到宿主機,例如把宿主機的 /www 目錄映射到Docker容器中的 /var/www 目錄
[root@localhost ~]# docker run -d -p 8080:80 -v /www:/var/www nginx:latest f14532375dc93a07f092e164149d384cdde6ae4a90b9de97bb7273c8b553f755
[root@localhost ~]# ll /www/ total 72 -rwxrwxrwx. 1 root root 657 Aug 28 16:10 aes1.lua -rwxrwxrwx. 1 root root 1088 Aug 28 18:33 aes2.lua drwxr-xr-x. 4 root root 4096 Sep 27 20:22 composer-demo -rwxrwxrwx. 1 root root 166 Jun 9 17:02 data.php -rwxrwxrwx. 1 root root 86 Jul 20 17:13 gcc.sh -rwxrwxrwx. 1 root root 15 Sep 1 2016 index.html -rwxrwxrwx. 1 root root 21 Sep 27 16:33 index.php -rwxrwxrwx. 1 root root 1076 Jul 20 18:05 mcrypt.c -rwxrwxrwx. 1 root root 3360 Jul 20 18:05 mcrypt.o -rwxrwxrwx. 1 root root 2590 Jul 20 17:42 mcrypt.php -rwxrwxrwx. 1 root root 7933 Jul 20 18:05 mcrypt.so -rwxrwxrwx. 1 root root 556 Jul 20 16:17 module.c -rwxrwxrwx. 1 root root 2624 Jul 20 16:12 module.o -rwxrwxrwx. 1 root root 110 Sep 5 11:03 redis.php drwxrwxrwx. 2 root root 4096 Aug 28 14:23 so -rwxrwxrwx. 1 root root 3058 Jul 20 17:59 test.lua -rwxrwxrwx. 1 root root 26 Sep 27 16:48 test.php [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f14532375dc9 nginx:latest "nginx -g 'daemon of 17 minutes ago Up 17 minutes 0.0.0.0:8080->80/tcp fervent_banach [root@localhost ~]# docker exec -it f14 /bin/bash root@f14532375dc9:/# ls -l /var/www total 72 -rwxrwxrwx. 1 root root 657 Aug 28 08:10 aes1.lua -rwxrwxrwx. 1 root root 1088 Aug 28 10:33 aes2.lua drwxr-xr-x. 4 root root 4096 Sep 27 12:22 composer-demo -rwxrwxrwx. 1 root root 166 Jun 9 09:02 data.php -rwxrwxrwx. 1 root root 86 Jul 20 09:13 gcc.sh -rwxrwxrwx. 1 root root 15 Sep 1 2016 index.html -rwxrwxrwx. 1 root root 21 Sep 27 08:33 index.php -rwxrwxrwx. 1 root root 1076 Jul 20 10:05 mcrypt.c -rwxrwxrwx. 1 root root 3360 Jul 20 10:05 mcrypt.o -rwxrwxrwx. 1 root root 2590 Jul 20 09:42 mcrypt.php -rwxrwxrwx. 1 root root 7933 Jul 20 10:05 mcrypt.so -rwxrwxrwx. 1 root root 556 Jul 20 08:17 module.c -rwxrwxrwx. 1 root root 2624 Jul 20 08:12 module.o -rwxrwxrwx. 1 root root 110 Sep 5 03:03 redis.php drwxrwxrwx. 2 root root 4096 Aug 28 06:23 so -rwxrwxrwx. 1 root root 3058 Jul 20 09:59 test.lua -rwxrwxrwx. 1 root root 26 Sep 27 08:48 test.php
把宿主機的程序映射到Docker容器中使用
可以看到這樣就可以容器中很方便的訪問宿主機的目錄和文件了。通常為了讓容器輕量,很多常用的系統命令在容器中並不存在, -v 參數可以多次使用來映射多個目錄,比如我們可以把宿主機的 /bin /usr/bin 等目錄映射到容器中,這樣我們就可以輕松的使用宿主機中的很多命令:[root@localhost ~]# docker run -d -p 8080:80 -v /www:/var/www -v /bin:/opt/bin -v /usr/bin:/opt/usr/bin nginx:latest 51d1452cc2bed5f36c719298acd4d4249251e4e7c3040eaa984d4528dc198ff3 [root@localhost ~]# docker exec -it 51d1 /bin/bash root@51d1452cc2be:/# ls /opt/bin/ arch cgdelete chown df env gawk ipcalc loadkeys mkdir netstat pwd rview su true usleep awk cgexec cp dmesg ex gettext iptables-xml logger mknod nice raw sed sync ulockmgr_server vi basename cgget cpio dnsdomainname false grep iptables-xml-1.4.7 login mktemp nisdomainname readlink setfont tar umount view bash cgset cut domainname fgrep gtar kbd_mode ls more ping rm sh taskset uname ypdomainname cat cgsnapshot dash dumpkeys find gunzip kill lsblk mount ping6 rmdir sleep touch unicode_start zcat cgclassify chgrp date echo findmnt gzip link lscgroup mountpoint plymouth rpm sort tracepath unicode_stop cgcreate chmod dd egrep fusermount hostname ln lssubsys mv ps rvi stty tracepath6 unlink root@51d1452cc2be:/# /opt/bin/cat /var/www/index.php <?php echo "hello"; root@51d1452cc2be:/# /opt/bin/vi /var/www/index.php
root@51d1452cc2be:/# /opt/bin/ls /var/www/ /opt/bin/ls: error while loading shared libraries: libcap.so.2: cannot open shared object file: No such file or directory
在宿主機中先用 ldd 命令查看一下 ls 需要鏈接哪些動態庫,可以看到基本都在 /lib64 目錄下
[root@localhost ~]# ldd /bin/ls linux-vdso.so.1 => (0x00007ffcf95c6000) libselinux.so.1 => /lib64/libselinux.so.1 (0x00007fce570a2000) librt.so.1 => /lib64/librt.so.1 (0x00007fce56e9a000) libcap.so.2 => /lib64/libcap.so.2 (0x00007fce56c95000) libacl.so.1 => /lib64/libacl.so.1 (0x00007fce56a8d000) libc.so.6 => /lib64/libc.so.6 (0x00007fce566f9000) libdl.so.2 => /lib64/libdl.so.2 (0x00007fce564f4000) /lib64/ld-linux-x86-64.so.2 (0x00007fce572ce000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fce562d7000) libattr.so.1 => /lib64/libattr.so.1 (0x00007fce560d2000)
把宿主機的 /lib64 目錄映射到容器中的 /opt/lib64 下:
[root@localhost ~]# docker run -d -p 8080:80 -v /www:/var/www -v /bin:/opt/bin -v /usr/bin:/opt/usr/bin -v /lib64:/opt/lib64 nginx:latest 90fb69fc990a14599c157496bfe3d75dac8fff3c34439e8ac6e76de1bf2daba5
[root@localhost ~]# docker exec -it 90f /bin/bash root@90fb69fc990a:/# /opt/bin/ls /var/www/ /opt/bin/ls: error while loading shared libraries: libcap.so.2: cannot open shared object file: No such file or directory root@90fb69fc990a:/# /opt/bin/touch /etc/ld.so.conf.d/lib64.conf root@90fb69fc990a:/# ls /etc/ld.so.conf.d/lib64.conf /etc/ld.so.conf.d/lib64.conf root@90fb69fc990a:/# echo /opt/lib64 > /etc/ld.so.conf.d/lib64.conf root@90fb69fc990a:/# /opt/bin/cat /etc/ld.so.conf.d/lib64.conf /opt/lib64 root@90fb69fc990a:/# ldconfig -v ldconfig: Path `/lib/x86_64-linux-gnu' given more than once ldconfig: Path `/usr/lib/x86_64-linux-gnu' given more than once /opt/lib64: liblvm2cmd.so.2.02 -> liblvm2cmd.so.2.02 libfreeblpriv3.so -> libfreeblpriv3.so libsemanage.so.1 -> libsemanage.so.1 libpci.so.3 -> libpci.so.3.1.10 ....
再來嘗試使用 /opt/bin/ls 命令:
root@90fb69fc990a:/# /opt/bin/ls /var/www/ aes1.lua aes2.lua composer-demo data.php gcc.sh index.html index.php mcrypt.c mcrypt.o mcrypt.php mcrypt.so module.c module.o redis.php so test.lua test.php
以上有點跑題了,讓我們回歸正題^^
修改容器中的nginx配置文件,把網站根目錄更改為 /var/www, 日志文件存儲到 /var/www/logs/ 目錄下,並在 /var/www/ 新建logs目錄, 然后重啟容器:
[root@localhost www]# docker stop 90f 90f [root@localhost www]# docker start 90f 90f [root@localhost www]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 90fb69fc990a nginx:latest "nginx -g 'daemon of 36 minutes ago Up 4 seconds 0.0.0.0:8080->80/tcp naughty_poincare [root@localhost www]# docker exec -it 90f /bin/bash /bin/bash: /opt/lib64/libtinfo.so.5: no version information available (required by /bin/bash) root@90fb69fc990a:/# ls /var/www/ aes1.lua aes2.lua composer-demo data.php gcc.sh index.html index.php logs mcrypt.c mcrypt.o mcrypt.php mcrypt.so module.c module.o redis.php so test.lua test.php
root@90fb69fc990a:/# touch /var/www/test.html root@90fb69fc990a:/# echo '<h1>hello docker</h1>' > /var/www/test.html root@90fb69fc990a:/# /bin/cat /var/www/test.html <h1>hello docker</h1> root@90fb69fc990a:/# exit exit [root@localhost www]# curl '127.0.0.1:8080/test.html' <h1>hello docker</h1> [root@localhost www]# cat /www/logs/access.log 172.17.42.1 - - [31/Oct/2017:08:05:46 +0000] "GET /test.html HTTP/1.1" 200 22 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.27.1 zlib/1.2.3 libidn/1.18 libssh2/1.4.2" "-"
以上 數據卷就介紹到這里, 接下來介紹 數據卷容器
如果要在多個容器之間共享數據,最簡便的方式就是使用數據卷容易,數據卷容器就是使用一個特定容器來做數據卷,多個其他容器可以同時掛載這個數據卷,從而達到共享數據的目的。
創建數據卷容器也是使用 docker run 跟 -v 參數,這里以 centos:v7.0 鏡像創建的容器作為數據卷容器:
[root@localhost www]# docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE mysql 5.6.38 52ac9f329cfd 5 days ago 299 MB nginx latest 2ecc072be0ec 3 weeks ago 108.3 MB centos v7.0 fae454d6fc7b 5 weeks ago 434.5 MB mysql 5.6.37 c6d1fd492efc 6 weeks ago 299 MB ubuntu 14.04 b44ce450cb60 6 weeks ago 188 MB quay.io/coreos/etcd v3.0.4 3b17a5f34e6c 15 months ago 43.3 MB index.tenxcloud.com/tenxcloud/ubuntu latest 2d4cb9fc6d24 23 months ago 251 MB [root@localhost www]# docker run -it -v /data --name datacon centos:v7.0 /bin/bash [root@6c281ef87114 /]# ls bin boot data dev etc fastboot home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
作為數據卷容器的容器不需要是運行狀態,docker run 跟 --volumes-from 參數可以指定某個容器作為數據卷
[root@localhost www]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 6c281ef87114 centos:v7.0 "/bin/bash" 12 minutes ago Exited (0) 4 minutes ago datacon [root@localhost www]# docker run -d -p 8080:80 --volumes-from=datacon --name=nginx-1 nginx:latest a1369262ba2596d81291fc2b114161bf0cb8dce436bbff0da7484be05f008998 [root@localhost www]# docker run -d -p 8081:80 --volumes-from=datacon --name=nginx-2 nginx:latest 98939ee55034233323e89f05254d8cfdef887fcdc2a5793f0bf7efefdd51e7e2 [root@localhost www]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 98939ee55034 nginx:latest "nginx -g 'daemon of 47 seconds ago Up 46 seconds 0.0.0.0:8081->80/tcp nginx-2 a1369262ba25 nginx:latest "nginx -g 'daemon of About a minute ago Up About a minute 0.0.0.0:8080->80/tcp nginx-1
上面創建了兩個nginx容器 nginx-1 和 nginx-2,並且都使用了datacon 作為數據卷容器,在其中一個容器的數據卷創建一個文件,再到另一個容器中查看:
[root@localhost www]# docker exec -it 989 /bin/bash root@98939ee55034:/# ls bin boot data dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var root@98939ee55034:/# cd /data/ root@98939ee55034:/data# touch docker.html root@98939ee55034:/data# /bin/echo 'hello docker' > docker.html root@98939ee55034:/data# cat docker.html hello docker root@98939ee55034:/data# exit exit [root@localhost www]# docker exec -it a13 /bin/bash root@a1369262ba25:/# ls /data docker.html root@a1369262ba25:/# cat /data/docker.html hello docker root@a1369262ba25:/# exit exit [root@localhost ~]# docker start -i 6c28 [root@6c281ef87114 /]# ls /data/ docker.html [root@6c281ef87114 /]# /bin/cat /data/docker.html hello docker
docker rm 跟 -v 參數可以在刪除容器的時候同時卸載數據卷。
[root@localhost ~]# docker rm -v nginx-1 nginx-1 [root@localhost ~]# docker rm -v nginx-2 nginx-2 [root@localhost ~]# docker rm -v 6c28 6c28