摘要:
很多的工作和软件安装或维护机器有关,这些工作还处理环境的特殊性。这些特殊性作为全局范围的依赖关系(如已知主机文件系统的位置)、硬编码的部署架构(代码或配置的环境检查),或数据局部性(存储在特定的不在部署体系结构以内的机器上的数据)。如果你的目标是建立低维护的系统,你应该努力减少这些事情。
Docker 有三个特定的功能,以帮助建立与环境无关的系统:
只读文件系统
环境变量注入
存储卷
处理卷是一个大主题,为了学习前两个功能,在本文的其余部分将改变对示例的需求。
WordPress 使用一个名为MySQL 的数据库程序来存储大部分数据,所以先确保运行WordPress
的容器是只读文件系统,是一个好主意。
1 只读文件系统
使用只读文件系统产生以下两个积极效果。首先,你对容器不能更改它所包含的文件产生信心;其次,你也会进一步树立信念:容器中的攻击者无法破坏文件。
为了在客户系统上使用--read-only 标志,从WordPress 镜像创建和启动一个容器:
docker run -d --name wp --read-only wordpress:4 |
完成这些步骤后,检查容器是否正在运行。你可使用任何先前介绍的方法,也可以直接检查容器元数据。如果指定的wp
容器正在运行,以下命令将输出为真,否则为假。
docker inspect --format "{{.State.Running}}" wp |
docker inspect 命令将显示Docker 为该容器保留的所有元数据(一个JSON 文件)。
格式选项会改变元数据。除了该容器的运行状态,本例中其会滤除元数据的所有字段。这个命令将简单地输出为错误。
在这种情况下,容器没有运行。为了找出原因,检查容器中的日志:
输出是这样的:
error: missing WORDPRESS_DB_HOST and MYSQL_PORT_3306_TCP environment variables Did you forget to --link some_mysql_container:mysql or set an external db with -e WORDPRESS_DB_HOST=hostname:port? |
看起来WordPress 有一个MySQL 数据库的依赖关系。数据库是一个程序,根据检索和搜索方式存储数据。好消息是,你可以使用Docker
安装MySQL,就像安装WordPress:
docker run -d --name wpdb \ -e MYSQL_ROOT_PASSWORD=ch2demo \ mysql:5 |
一旦启动后,会创建一个不同的WordPress 容器,并链接到这个新的数据库容器中:
再检查一次,WordPress 是否正常运行:
docker inspect --format "{{.State.Running}}" wp2 |
你可以得知WordPress 失败后重新启动。检查日志以确定原因:
应该有类似以下的日志:
... Read-only file system: AH00023: Couldn't create the rewrite-map mutex (file /var/lock/apache2/rewrite-map.1) |
同样是WordPress 失败后重新启动,但这次的问题是,它试图写一个锁定文件到特定的位置。这是启动的必要组成部分,并无特殊。在这个示例中,需要为只读文件系统增加异常处理。你需要使用卷来做这个异常处理。使用下面的命令启动WordPress,不会有任何问题:
更新版本后你能用的脚本看上去像是这样:
SQL_CID=$(docker create -e MYSQL_ROOT_PASSWORD=ch2demo mysql:5)
docker start $SQL_CID
MAILER_CID=$(docker create dockerinaction/ch2_mailer)
docker start $MAILER_CID
WP_CID=$(docker create --link $SQL_CID:mysql
-p 80 \
-v /run/lock/apache2/ -v /run/apache2/ \
--read-only wordpress:4)
docker start $WP_CID
AGENT_CID=$(docker create --link $WP_CID:insideweb
\
--link $MAILER_CID:insidemailer \
dockerinaction/ch2_agent)
docker start $AGENT_CID |
恭喜你,现在你应该有了一个正在运行的WordPress 容器!通过使用只读文件系统,以及链接WordPress
到另一个运行着数据库的容器,可以确保运行WordPress 镜像的容器永远不会改变。这意味着,如果运行客户的WordPress
博客程序的机器出了问题,可轻松在其他地方启动该容器的另一个副本。
但是这一设计有两个问题。首先,数据库和WordPress 的容器运行在同一个机器上。其次,WordPress
对重要的设置,如数据库名称、管理用户、管理密码、数据库加盐等使用默认值。为了解决这个问题,你可以创建多个版本的WordPress
软件,每一个客户都有一个特殊的配置。这样做会使简单的配置脚本变成一个在创建镜像时写入文件的怪物。通过使用环境变量来注入配置则是一个更好的方式。
2 环境变量的注入
环境变量是通过其执行上下文提供给程序的键值对。它可以让你在改变一个程序的配置时,无须修改任何文件或更改用于启动该程序的命令。
Docker 使用环境变量来传达相关信息,包括容器的守护选项、容器的主机名,以及其他在容器中运行程序的实用信息。Docker
还为用户提供了一个机制,可将环境变量注入到一个新的容器。那些期望通过环境变量获取重要信息的程序,可在容器创建时就进行配置。幸运的是,WordPress
就是这样一个程序。
在深入WordPress 的细节之前,尝试注入和观察你的环境变量。UNIX 命令env 显示当前执行上下文(终端)中的所有环境变量。要查看注入的环境变量,请使用以下命令:
--env 标志或-e 缩写,可用于注入任何环境变量。如果变量已经由镜像或Docker 设置,则该值将被覆盖。容器内部运行程序的方式,可以依赖于这种变量。WordPress
遵循以下环境变量:
WORDPRESS_DB_HOST WORDPRESS_DB_USER WORDPRESS_DB_PASSWORD WORDPRESS_DB_NAME WORDPRESS_AUTH_KEY WORDPRESS_SECURE_AUTH_KEY WORDPRESS_LOGGED_IN_KEY WORDPRESS_NONCE_KEY WORDPRESS_AUTH_SALT WORDPRESS_SECURE_AUTH_SALT WORDPRESS_LOGGED_IN_SALT WORDPRESS_NONCE_SALT
|
提示 这个示例忽略了KEY 和SALT 变量,但任何实际的生产系统绝对应该设置这些值。
开始之前,你应该解决数据库和WordPress 容器在同一个机器上运行的问题。不是使用链接来满足WordPress
的数据库依赖,而是注入WORDPRESS_DB_HOST 变量的值:
docker create --env WORDPRESS_DB_HOST=<my database hostname> wordpress:4 |
这个示例会创建(并不启动)WordPress 容器。不管你在中指定的是什么,该容器都会试着连上一个MySQL
数据库。
由于远程数据库可能不会使用任何默认的用户名和密码,你就必须同时注入这些设置。假设数据库管理员是养猫爱好者且痛恨强密码:
docker create \ --env WORDPRESS_DB_HOST=<my database hostname> \ --env WORDPRESS_DB_USER=site_admin \ --env WORDPRESS_DB_PASSWORD=MeowMix42 \ wordpress:4 |
使用环境变量注入这一方法,能帮助你区分WordPress 容器和MySQL 容器之间的物理联系。由于数据库和客户的WordPress
网站都在同一台机器上,你仍然需要解决前面提到的第二个问题——所有的网站都使用相同的默认数据库名称。你需要为每一个独立的站点设置数据库名称以环境变量的方式注入:
你已经解决了这些问题,现在可以修改配置脚本了。首先,设置机器只能运行一个MySQL 容器:
DB_CID=$(docker run -d -e MYSQL_ROOT_PASSWORD=ch2demo mysql:5) MAILER_CID=$(docker run -d dockerinaction/ch2_mailer) |
那么网站配置脚本将是这样的:
这个新脚本将为每一位客户启动WordPress 实例和监控器,并将这些容器以及一个单独的邮件程序和MySQL
数据库彼此连接。WordPress 容器在被销毁、重新启动、升级的同时,完全不用担心数据会丢失。如图所示就是这种架构。
每个WordPress 和监控器容器使用相同的数据库和邮件服务
客户对当前交付的所有工作成果很满意。但有一件事可能会比较烦人。在早期的测试中,你发现监视器在该网站不可用时,的确可以准确通知邮件服务器,但重新启动该网站和监控器需要手动实现。要是系统在检测到故障时,能尝试自动恢复就更好了。Docker
对此提供了重启的策略,但仍不够稳定。
|