容器在运行的过程中,难免会涉及到文件的读写,比如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
再到容器中查看 /var/www 目录的情况
[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
比如 ls 命令由于用到了 libcap.so.2 动态链接库,而容器中找不到这个链接库,所有使用这个命令时出现了错误,如果确有需要使用该命令,可以把这个链接库在宿主机的目录也映射到容器中,以上述的 ls命令为例:
在宿主机中先用 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
进入容器中, 新建 /etc/ld.so.conf.d/lib64.conf,并写入 /opt/lib64,使用 ldconfig -v 来重新搜索动态库
[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
可以看到映射过来的ls命令可以正常使用了。
以上有点跑题了,让我们回归正题^^
修改容器中的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
在 /var/www/ 下新建一个 html,然后在宿主机访问这个html:
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" "-"
可以直接在宿主机中查看nginx 的日志
以上 数据卷就介绍到这里, 接下来介绍 数据卷容器
如果要在多个容器之间共享数据,最简便的方式就是使用数据卷容易,数据卷容器就是使用一个特定容器来做数据卷,多个其他容器可以同时挂载这个数据卷,从而达到共享数据的目的。
创建数据卷容器也是使用 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
以上就是关于Docker对于文件的简单操作,希望对大家有帮助^^