多个 Docker 容器之间共享数据
Q:容器磁盘可以限制配额么?
A:可以。对于 devicemapper, btrfs, zfs 来说,可以通过 --storage-opt size=100G 这种形式限制 rootfs 的大小。
Q:容器内的数据该保存在镜像里还是物理机里?
A:如果所谓数据是指运行时动态的数据,那么这部分数据文件不应该保存于镜像内。在运行时要保持容器基础文件不可变的特性,而变化部分使用挂载宿主目录,或者数据卷来解决。
Q:看到总说要保持容器无状态,那什么是无状态?
A:这里说到的有两个层面的无状态:
容器存储层的无状态
这里提到的存储层是指用于存储镜像、容器各个层的存储,一般是Union FS,如 AUFS,或者是使用块设备的一些机制(如 snapshot )进行模拟,如 devicemapper。Union FS 这类存储系统,相当于是在现有存储上,再加一层或多层存储,这类存储的读写性能并不好。并且对于 CentOS 这类只能使用 devicemapper 的系统而言,存储层的读写还经常出 bug。因此,在 Docker 使用过程中,要避免存储层的读写。频繁读写的部分,应该使用卷。需要持久化的部分,可以使用命名卷进行持久化。由于命名卷的生存周期和容器不同,容器消亡重建,卷不会跟随消亡。所以容器可以随便删了重新run,而其挂载的卷则会保持之前的数据。
服务层面的无状态
使用卷持久化容器状态,虽然从存储层的角度看,是无状态的,但是从服务层面看,这个服务是有状态的。从服务层面上说,也存在无状态服务。就是说服务本身不需要写入任何文件。比如前端 nginx,它不需要写入任何文件(日志走Docker日志驱动),中间的 php, node.js 等服务,可能也不需要本地存储,它们所需的数据都在 redis, mysql, mongodb 中了。这类服务,由于不需要卷,也不发生本地写操作,删除、重启、不保存自身状态,并不影响服务运行,它们都是无状态服务。这类服务由于不需要状态迁移,不需要分布式存储,因此它们的集群调度更方便。
Q:卷和挂载目录有什么区别?
A:卷 (Docker Volume) 是受控存储,是由 Docker 引擎进行管理维护的。因此使用卷,你可以不必处理 uid、SELinux 等各种权限问题,Docker 引擎在建立卷时会自动添加安全规则,以及根据挂载点调整权限。并且可以统一列表、添加、删除。另外,除了本地卷外,还支持网络卷、分布式卷。
而挂载目录那就没人管了,属于用户自行维护。就必须手动处理所有权限问题。特别是在 CentOS 上,很多人碰到 Permission Denied,就是因为没有使用卷,而是挂载目录,而且还对 SELinux 安全权限一无所知导致。
Q:多个 Docker 容器之间共享数据怎么办?NFS ?
A:如果是同一个宿主,那么可以绑定同一个数据卷,当然,程序上要处理好并发问题。
如果是不同宿主,则可以使用分布式数据卷驱动,让分布在不同宿主的容器都可以访问到的分布式存储的位置。如S3之类。