Docker 学习的道路真的是学无止尽,以下笔者列出三十天里没有提到的东西,有兴趣的读者可以用关键字查询。
最後,来个小测验考考大家是不是对 Docker 更了解:
第一题的答案是 (A)
A 描述错误:docker run
可以基於 image 产生 container,所以第一句话是正确的;相对地,docker commit
可以藉由 container 产生 image,所以第二句话是错误的。
B 描述正确:docker run <IMAGE ID>
指令中, 为 SHA256 digest,同个 digest 的内容无法改变。而 container 内容则是可变的,比方说进入 Nginx container 新增 HTML 档,即可立刻使用浏览器看到内容。
C 描述正确:Image 上 run 一个 container 时,可以使用 docker rmi -f <IMAGE ID>
强制把 image 移除。虽然无法再使用该 Digest 再次启动 container,但实际上 image 内容依然是存在的,因为重新 pull image 会发现 Already exists
的关键字。实际测试指令如下:
$ docker run php:7.4 php -v
Unable to find image 'php:7.4' locally
7.4: Pulling from library/php
...
$ docker rmi -f php:7.4
Untagged: php:7.4
Untagged: php@sha256:...
Deleted: sha256:...
$ docker pull php:7.4
7.4: Pulling from library/php
xxxxxxxxxxxx: Already exists
xxxxxxxxxxxx: Already exists
...
了解 image 与 container 的关系後,才能进一步了解 Docker 是如何建置、如何加速建置、启动 container 等。
第二题的答案是:(C)
此题目要考虑下列两件事:
A 与 B 很明显正确,container 因为少了 OS 层,当然启动速度与记忆体使用量,都相较 VM 来的有优势。
C 假设过去 VM 习惯使用 Ubuntu 或是任一种 OS,现在 container 是否必须要用相同的 OS 才能正常运行(VM 跟 Container 也可以交换反过来看)?答案当然是「非必要」的,如官方 Redis image 就提供了 Debian 和 Alpine 等选择,即使作业系统不一样,只要把程序或设定做好,系统一样能正常运作。
Container 用起来跟 VM 很类似,但要记得它们本质是不同的。而不管 VM 或 container 都得经过调校才能发挥最大的优势。
第三题的答案是:(C)
A 与 B 其实是差不多的,差别是 B 会把 container 砍掉。
C 很明显是不能做的。进去安装 Vim 或相关除错工具明显错误就不提了,如果是为了看 log,参考 12 Factor Logs,它应该能在其他地方查得到,而不是进 container 查;如果是进去调整参数等行为,则会不符合 12 Factor Build, release, run 严格分离的原则。
现在 container 都是交由 Kubernetes 等 container orchestration 系统负责这些维运任务,但开发者也有必要了解这类问题的处理方法,才有办法写出符合 container 架构的程序。
一次性的特色可以参考 Create ephemeral containers。
第四题的答案是:(A)
参考 Decouple applications,Docker 官方是这麽说的:
Limiting each container to one process is a good rule of thumb, but it is not a hard and fast rule.
上面五种 container,唯独 Apache with PHP-FPM(FastCGI)container 是比较不符合的,因为它必须启动做两件不同任务的 process。可以注意到在 DockerHub 找到类似的 image 的 CMD,都必须要使用 Supervisor 或类似的工具来管理 process。
顺带一提,官方也没有提供 Apache + PHP-FPM 或 Nginx + PHP-FPM 的 image,而是提供只有 PHP-FPM 的 image,或是 Apache + PHP-CGI 的 image。
这概念与 SOLID 里 SRP 的优点一样:只做一件事,架构不会复杂,除错会更容易。
第四题的答案是:(E)
A 的问题:部署上线後居然可以跑单元测试?这代表测试程序码和单元测试套件也一并被部署上线,这不符合 Don’t install unnecessary packages。
正确的做法:在建置 image 前或是 Use multi-stage builds 在一开始的阶段做单元测试,最终仅部署做完单元测试後的程序码。
相对地,部署上线後,可以做冒烟测试(smoke testing)。
B 的问题:VOLUME 官方不建议用来放程序,而是放额外要保存的资料,如 MySQL 的 Dockerfile 就有设定 VOLUME /var/lib/mysql
是存放资料库档案。
正确的做法:程序上线应该透过建置新的 image,跑新的 container 来取代旧的。
可以试着反过来思考,为何我们会觉得 Docker 上跑 MySQL / Redis / Apache 很快速方便?因为它们把程序都包在 image 里了。
C 的问题:「把机敏资讯加入 image 里」这句话的意思就是,只要有办法下载 image 就能得到机敏资讯。当然可以限制下载 image 的权限,但还是有另一个问题是难以做到环境同步,因为线上环境跟测试环境会是不同的 image--因为机敏资讯设定通常是不一样的。
正确的做法:使用 ENV
环境参数(参考 12 Factor Config),把机敏资讯存在环境。
Docker 真的是学无止尽,虽然笔者跟他相处了很久,但要写的时候,还是得东查西查。
希望这次的铁人赛能帮助到大家,感谢收看。
>>: Day30 - 逆向 WannaCry 病毒,想哭病毒?
引言 昨天的题目学习到进位制以及「 ASCII code <-> 字元」转换, 关於 ...
【YC的迷路青春】 如果不要用预设的路径,例如专案是用tomcat起的,我们不想看tomcat的lo...
今天要谈的是AWS(Amazon Web Services)云端服务, 这个也是众多云端服务当中,我...
函式陈述式与函式表达式 函式陈述式:之前直接定义 function 的方式 会被提升到最上面,所以可...
昨天我们耗尽洪荒之力, 终於用 terraform 配置好整个基础设施, 今天我们将继续环境操作, ...