如何记住过长的 Docker 容器启动命令

背景

容器启动命令很难记吗?先来看一条吧:

docker run --name xx-xxxxx-proxy \ 
  -p 26379:6379 -p 18080:8080 \
  -v /opt/docker-volumes/xx-xxxxx-proxy/opt/:/opt/ \
  -d 192.168.1.2/xxx-debug/xxxxx-proxy:2

这可不是我随便胡写吓唬人的,而是我在实际工作中真真切切编写的容器启动命令(敏感信息已用等长的x替换),更可怕的是,像这样一长串的命令还有六十多条。

记住这些命令几乎是不可能的事,但是如果不记住,问题来了:一段时间后,一个正在运行的容器需要重建(删掉容器再用新版本镜像启动一个),可这时候发现竟然没有人知道这个容器当初是怎么启动的。这时候唯一的办法是查看该容器各项配置信息,并据此反推其启动命令——然而这太难了,也太不靠谱了。

前些日子,我在公司做关于 Docker 的技术分享时,阐述了这个问题,称之为“容器启动信息的丢失”,当时提供如下几个方案:

  1. 反复背诵启动命令,形成长期记忆并定期温习;
  2. 将命令写入文档;
  3. 使用 Docker Compose;
  4. 使用 Docker Make。

第一条是开玩笑的,不要当真。剩下三个方法是可行的,但不一定都推荐。

写入文档

刚才我说了,像开头那样的鬼命令还有六十多条,没错,为了不忘记这六十条命令,我把它们全记在了文档里。这看似是一个机智的做法,然而作为切身实践者,我非常不推荐这么干。

由于一些命令不可能第一次就写完善,我可能需要反复修改参数、反复测试,这样一来,文档里记的内容也要随着反复修改。调整命令 -> 记录文档 -> 测试容器 -> 测试不理想 -> 调整命令 -> 记录文档 -> ……反复这样做,未免太繁琐了,于是我投机取巧,改了之后不要立即记,先测,差不过了再记。可是我又反复地陷入“我刚是不是忘了记了?记着的这个是最新的吗?”这类恐慌中,苦不堪言。

另一个麻烦是,这些堆砌起来的记录检索起来往往不方便,我试图查看某一台机器的某一个容器的启动命令是啥时,往往要在文档里找半天——前提条件还是文档及时更新了,且没有弄丢,否则就完蛋了。

我在一通挣扎后完成了任务,也产生了许多貌似只有我看得懂的文档。

结论是,我再也不干这蠢事了。

Docker Compose

事实上我在干这蠢事时,知道 Docker Compose 这个工具,用起来也不手生,但当时没有用是有苦衷的,卖个关子,先看看 Docker Compose 是什么。

Docker Compose 是一个用来定义和运行复杂应用的 Docker 工具。使用 Docker Compose,你可以在一个文件中定义一个多容器应用,然后使用一条命令来启动你的应用,完成一切工作。

值得注意的是 Docker Compose 提出了一个“应用”的概念,一个应用可以包含一个或多个容器。所以要记住一个应用的所有容器的所有启动参数,是难上加难。所以 Docker Compose 的做法是,让用户将这些参数以一定的格式写入到一个文件中,依托这个文件,用户可以以简单的命令完成复杂的操作。

我非常推荐使用 Docker Compose,并认定这才是 Docker 容器正确的打开方式。它的具体用法可见官方文档这里就不做展开了,仅举个例子展示其优越性。

我以开头那条命令为例。首先,我需要写一个配置文件 docker-compose.yml

version: '2'

services:
  proxy:
    name: xx-xxxxx-proxy
    image: 192.168.1.2/xxx-debug/xxxxx-proxy:2
    ports:
     - "26379:6379"
     - "18080:8080"
    volumes:
     - /opt/docker-volumes/xx-xxxxx-proxy/opt/:/opt/

这文件写起来可能并不轻松,但一劳永逸,用起来时就简单了:

docker-compose up -d #创建并启动容器,相关参数自动从 docker-compose.yml 里读取
docker-compose logs -f #查看容器日志
docker-compose stop #停止容器

docker-compose 命令的用法和 docker 命令几乎一模一样,非常容易上手,唯一的不足可能是 docker-compose 一词太长了,可以用别名缩短下,我一般缩短成 dockerc 来用。

话说回来,既然 Docker Compose 这么好用,为什么我之前不用呢?不是不想用,没法儿用。当时部门给我的所有机器都是 CentOS 6,内核版本不够高,不得已,装了低版本的 Docker,而 Docker Compose 恰恰不支持该版本的的 Docker,这就让我非常尴尬了。

事后我查过此事,当时装的 Docker 版本应该是 1.7.1,而 Docker Compose 最低版本(1.2)支持最低版本的 Docker 是 1.6.0,按理说我是应该可以在 CentOS 6 上使用 Docker Compose 的,但当时我明明试过各版本的 Docker Compose 的,均无法在 CentOS 6 上使用,这就是个谜了。

不过为这个谜费神也没多大必要,因为后来,CentOS 6 无法装高版本的 Docker 这一事实引发了一系列让人头疼的问题,部门也表示理解,陆陆续续地重装了一些服务器,升到了 CentOS 7,很多问题便迎刃而解。

这里也给用 CentOS 6 跑 Docker 的同志提个醒,Docker 对系统内核的版本是敏感的,CentOS 6 内核版本对 Docker 而言偏低,所以赶紧赶紧升吧,早升早平安。

Docker Make

Docker Make 是啥?它是我自己写的小工具,你自然搜索不到咯。

这个工具是我在四处碰壁之后,开了个脑洞,利用 make 命令写的一个脚本工具。我参考了 Docker Compose 的套路,将繁杂的参数写进了 Makefile,使用时仅需要输入很简单的命令即可。

下面插播一条广告:

广告开始。


  1. Docker Make 可用于任何 Linux 发行版、任何版本的 Docker;
  2. Docker Make 比 Docker Compose 更轻量,仅仅是几行脚本写的工具,详见:https://github.com/wolfogre/docker-make
  3. 安装 Docker Make 更简单,只需要一条命令即可秒装。
  4. docker-compose.yml 文件的写法与 docker 命令原始的参数写法完全不一样,两者转换起来麻烦且费时费脑,而 Docker Make 的 Makefile 写法几乎与原生的 Docker 命令一模一样;
  5. Docker Make 提供了一些新命令,如“摧毁”:make distroy,可以删除容器并清理所有磁盘映射的文件;
  6. Docker Make 非常容易定制化,如定义启动容器前将某文件拷贝到某处、定义新的命令make fuck,等等等等。

广告结束。

同样,这里展示一下 Docker Make 的用法,仍然用开头那段命令做例子。

首先我们需要安装一下 Docker Make(说是说“安装”,其实就是下载、解压而已):

cd ~ #选一个位置放置 docker-make,如主目录
curl https://raw.githubusercontent.com/wolfogre/docker-make/master/auto-download.sh | sh -

这个时候可以看到主目录多了一个 docker-make 目录,进去后可以看到目录结构为:

└── docker-make
    ├── auto-download.sh
    ├── Generalfile
    ├── Helpfile
    ├── LICENSE
    ├── README.md
    └── sample
        └── Makefile

其中 Generalfile 存放通用命令,Helpfile 存放帮助信息,sample 目录是一个示例,其他文件均是闲杂人等,删了也没关系。

拷贝一份 sample 来定义新容器:

cp -r sample/ xx-xxxxx-proxy/
cd xx-xxxxx-proxy/

根据实际需要修改 Makefile,大多数时候只需要修改 NAME 的值和 run: 下面的一行即可。此处改为:

NAME=xx-xxxxx-proxy
VOLUME=$(VOLUME_ROOT)/$(NAME)

include ../Generalfile

run:
    docker run --name=$(NAME) -v $(VOLUME)/opt/:/opt/ -p 26379:6379 -p 18080:8080 -d 192.168.1.2/xxx-debug/xxxxx-proxy:2

可见内容几乎可以照抄原始的 docker run 命令,所以写起来更加简单。用起来也非常方便,目前支持的命令有:

make help #显示帮助信息
make run #创建并启动容器
make start #启动容器
make stop #停止容器
make restart #重启容器
make logs #查看容器日志,自动 follow
make exec #以 sh 进入容器
make rm #删除容器,若容器在运行中则自动停止
make distroy #摧毁容器,若容器在运行中则自动停止,之后删除容器、删除所有磁盘映射文件

总结

综合来看,Docker Make 不失为一个在特定场景下解决问题的好工具,但也是一个不入主流的野路子,更多的时候,还是建议使用 Docker Compose,它的功能更多,应用面更广,更面向未来。

而无论哪一个工具,我都坚信它们只是一个在过渡时期,或在小规模应用场景下,帮忙排忧解难的小玩意儿。随着自动化部署、容器集群管理等技术的推进和推广,手敲 docker run 命令迟早会成为历史,就更别提 docker-compose runmake run 了。


参考: