本番運用のための理想的なDockerfileについての考察

首先

在我之前参与的项目中,使用Docker镜像来运行应用程序始终存在重量过大的问题。

Dockerイメージが重いと、良いことは一つもありません。
私の経験上で主要な具体例を上げると…

    • 稼働アプリケーションのパフォーマンス低下 (無駄なリソース消費)

 

    • ビルド(CI)にかかる時間の増大

 

    ローカル開発が重くてストレス (開発にかかる運用負荷の増大)

实际上,这种情况已经发生了。

どういうコンテナを作るべきかは、Googleがベストプラクティスを提唱しているものが有名で、以下のatmarkITの記事などでも紹介されています。

你设想的是什么样的环境?

在本节中,我们将讨论无状态的网络服务的前端部分。

在概述越具体的内容之前,最终目标是实现像 Linux + Apache + PHP 这样的常见的 WEB 服务器容器作为前端。

DBやキャッシュ周りは、SaaSや他のコンテナに任せるものと想定します。

在实际应用中,您如何处理层次结构?

先ほどのGoogleのプラクティスにもある通り、公開されているイメージをそのまま自分の (自社の) サービスに適用できるケースは少ないでしょう。

根据某种公开形象,编写Dockerfile以引入缺少的库和包,并构建并部署服务。

ここでまず考えなくてはならないポイントは、ビルドするレイヤーは通常1つでは収まらないということです。

需要考虑的是具体的CI事项。

    • OSやミドルウェアなど、基本的な環境を定義してビルドする (1層目)

 

    CIを回して git clone を行い、最新のアプリ状態をビルドする (2層目)

という、最低2層の構成とすべきでしょう。

レイヤーは少なければ少ないほど、完成するイメージは軽くなります。
ただし、CIを回してビルドするイメージを毎回最初から作っていたのでは、どんなに軽くできるテクニックを駆使していても、毎回相応のビルド時間が発生するので現実的ではありません。

「1層目」について、同様の環境で動作するいくつかのアプリケーションは、同じイメージを共用する方が良いでしょう。

これは、セキュリティにとっても利点があります。
例えばOSに脆弱性が出たときに、アプリケーション側のDockerfileの FROM を書き換えることで、各アプリケーション一律にセキュリティ対応が行われた状態で、すぐデプロイし直せることがその理由です。

実際、私がかつて携わっていた案件でも「1層目」を共通化すること自体はネガティブな要素や意見はありませんでした。

場合によっては、アプリケーションごとの差を吸収するために3層としなければならないケースもあるかも知れません。詳しくは個別的な検討が必要でしょう。

另外,从这之后

    • 1層目のビルドイメージ … ベースイメージ

 

    2層目のビルドイメージ … CIイメージ

という呼び方で話を進めたいと思います。

反模式

虽然这纯粹是我的个人看法,但我将根据我的过去经验,提出一个不好的基础形象组成的方式。

    1. VMで稼働してるインフラの作り方をDockerfileに適用する

 

    1. 言語のバージョンをもってイメージを場合分けする

 

    1. 公開されているイメージを生かさない

 

    1. OSのディストリビューションにこだわる

 

    Dockerfileとして軽量にできる記法/手法を使わない

主にこの5点だと考えます。
カテゴリごとというよりも、ハマりそうな順に書いてます。。。

由于在一篇文章中可能不太容易理解,所以我会在下面以详细说明的方式进行逐一解释。

1. VMで稼働してるインフラの作り方をDockerfileに適用する

これから本番でDockerを採用しようとする企業 (チーム) にとって、最もあると思われるパターン。例えば AWS EC2 のオートスケール環境で稼働しているアプリケーションをコンテナ化する…などの要件ではないかと思います。

一見すると、Dockerfileはシェルスクリプトとほぼ同様に読めるので、VMで『安定稼働』しているサーバインフラの作りをそのまま、あるいは似たものを移植したくなるかも知れません。

これはアンチパターンです。

本項では主にPHP環境を扱うのですが、PHPのインストールのやり方としては、基本的には以下のような3つの方法が考えられます。

    • ソースインストール (公式推奨)

 

    • yum や apt などOSのリポジトリ管理ツールからインストール

 

    .rpm や .deb などのパッケージファイルを使用してインストール

如果在虚拟机上构建的话,很可能会选择其中一种方法,但不应该在Docker上做同样的事情。

无论采取哪种方法,处理上都会有很高的成本,给形象增加了负担。

詳しくは後ほどまた触れていきます。

2. 言語のバージョンをもってイメージを場合分けする

先ほど、「同様の環境で動作するいくつかのアプリケーションは、同じイメージを共用する方が良い」と書きました。

如果从结论上来写,这并不是指正在讨论PHP5.6开发的应用和PHP7.0开发的应用之间的差异。

ここでのアンチパターンは、以下の内容を指しています。

同じPHP7.0のアプリケーションでも、フレームワークが異なると必要なライブラリは異なってきます。
そのため、複数のフレームワークに対応させたイメージは、多数のライブラリを盛り込む必要があり、より重量級になりがちです。

また、同言語の同バージョンを後から別のフレームワークに対応させようとした場合、追加で別のソフトウェアを導入する必要も生じます。
これは結果的に、他のアプリケーションに影響を与え安定性を損なう原因になったり、Dockerfileの複雑化・さらなる重量化をもたらします。

重要なのはコミュニケーションの方法です。 yǔ de , de shì de .)

    • フレームワークごと

 

    フレームワークのバージョンごと

在这方面,我认为以两个角度分开并努力达到共同化更为自然。

然而,如果使用不依赖框架的语言或者框架本身的开发速度很慢(经常有只想升级语言版本的需求),则情况可能不适用。我认为需要考虑其他方案。

3. 不利用已公开的形象

    就像我之前写的那样,从零开始构建语言环境的过程非常繁重。

Docker Hubには多数のイメージが用意されています。
軽いDockerイメージを作るコツは、実現したい環境に近い公式イメージを基にしてDockerfileを書くことです。

具体的には、上記のようにアプリケーションを動作させるための言語環境を基準にした公式イメージを使用するのがより良いと考えます。

为什么要创建Docker镜像?

对于这个问题,我们应该明确回答为了运行应用程序。选择与目标匹配的最佳图像是我们所需的第一步。

不考虑基本轻量化和最优图像,这就是反模式的表现。

Node.js、Python、Go、Ruby等等……由于每种语言都有官方的文档,所以最好先查看官方文档。

https://hub.docker.com/_/node/ -> Node的Docker镜像仓库
https://hub.docker.com/_/python/ -> Python的Docker镜像仓库
https://hub.docker.com/_/golang/ -> Golang的Docker镜像仓库
https://hub.docker.com/_/ruby/ -> Ruby的Docker镜像仓库

当谈到PHP环境的构建时,PHP扩展的发展历史相当复杂,大致可以分为以下三种模式。

    1. 在PHP源代码中包含的东西

由外部提供的使用C语言开发的(通过pecl命令安装)
由外部提供的使用PHP开发的(通过composer命令安装)

在考虑PHP的实际运用时,需要掌握无法交由composer处理的1. 2.的处理方法。

另外,在https://hub.docker.com/_/php上写着如下内容,

我们提供了辅助脚本docker-php-ext-configure、docker-php-ext-install和docker-php-ext-enable,以便更轻松地安装PHP扩展。

另外,作为一个例子,下面是一个Dockerfile的介绍。

FROM php:7.4-fpm
RUN apt-get update && apt-get install -y \
        libfreetype6-dev \
        libjpeg62-turbo-dev \
        libpng-dev \
    && docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install -j$(nproc) gd

在这里,作为一个例子提到了安装 php-gd,但除了这个之外,一般来说还有多种方法,比如在操作系统的发行版或 PHP 自身的安装过程中都可以进行。

如果能够仅通过docker-php-ext-install等命令来处理这个问题,可能会更有好处……我认为。但是,归结起来,这种方法并不成功……请参阅后续详细说明。

4. 对操作系统的发行版有所偏好

对于那些稳定运营着现有服务的工程师(尤其是那些深度参与运营的工程师来说),他们过去使用过并且深感情绪依恋的Linux发行版是一个不可忽视的重要因素。

然而,就像在3中所述,创建容器环境的唯一目的就是运行应用程序,而不考虑操作系统的类型。

在类似容器的定义性(声明性)基础设施中,只要确定其作为逻辑的正常运行,就可以安全地进行稳定运作。
在从VM环境迁移到容器上的时候,特别需要注重进行全面的功能测试。
(当然,适当的扩展或自动扩展也是必要的)

在本文中,我们将使用一种轻量级Linux发行版Alpine。

阿尔卑斯是近年来在Docker社区备受关注的,同时在查看Docker Hub的官方PHP镜像时,发现它非常轻量,相较于标准的Debian来说。

不使用可以使Dockerfile更简洁轻量的语法/方法。

在这里,我们主要介绍在网上搜索时经常出现的一系列信息。

即使无法立即大幅更改正在使用的Dockerfile结构,如果尚未执行以下操作,仍可期望适当的轻量化。

    インストールキャッシュを削除する (apt, yum, apk など利用する場合)
例:
 (※ 実際にはDockerfileの形式に合わせた最適化が必要)

# apt clean
 または
# rm -rf /var/cache/apt/*
    • ソースインストールを行う場合は、tarボールやビルドしたソースを削除する

 

    → 一般のサーバ運用であれば保持しておくべきですが、コンテナでは継続運用しないため。
例:
 (※ 実際にはDockerfileの形式に合わせた最適化が必要)

# cd /usr/local/src/httpd-2.4.9
# ./configure --prefix=/opt/httpd/httpd-2.4.9 --with-apr=/opt/apr/apr-1.5.1 --with-apr-util=/opt/apr-util/apr-util-1.5.3
# make
# make install

// この部分が該当
# make clean
# rm -rf /usr/local/src/httpd-2.4.9/
    • 場合によりマルチステージビルドを活用する

 

    • → 一般に公式イメージは軽いのと、コンパイルのステージを分離して複数イメージを利用することが軽量化に効果を発揮する場合があります。

 

    • ADD より COPY を利用する

 

    • → 詳細は公式に任せて割愛しますが、機能が違うので COPY を使いましょう。

 

    • https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#add-or-copy

 

    • RUN, COPY などの処理はなるべくまとめる

 

    • → 具体的には、 \ や && で結合しRUNは1回にします。

 

    •   RUNを次々に並べて書くようなやり方はスマートでないだけでなく、複雑な処理になるとイメージサイズに影響する場合があるようです。

 

    • ビルドディレクトリ配下に余計なものを置かない

 

    • → COPY の使い方しだいで運ばれてしまいます…

 

      何かの事情で避けられない場合は .dockerignore を書きましょう。

尝试创建一个可以运行Laravel 7.x的基本镜像。

手元に Laravel 7.x を利用して開発したテストアプリケーションがあるため、これを本番相当で動作可能とするユースケースを考えていきます。

まず、Docker HubのPHP公式から適当と思われるイメージを見繕います。

鑑於前提是需要 PHP >= 7.2.5,因此我希望將 PHP 的版本設定為最接近最低限的版本 7.3。
https://readouble.com/laravel/7.x/ja/installation.html

在这里,需要考虑的要点有四个。

    • AlpineがベースOSとなっていること

 

    • 2.4系のApacheが最初から入っていると、なおベスト

 

    • ZTSは必要ない

 

    worker系のMPMは使用しないので、FPMも必要ない

大致上看起来是这样的。

    • php:7.3-alpine3.12

 

    php:7.3-apache

从重点的角度来看,没有任何已安装了Alpine和Apache的选项可供选择。关于php:7.3-apache,操作系统是Debian 10(buster)。

一旦在本地电脑上将它们拉取,进行原始图像尺寸的比较。

$ docker pull php:7.3-alpine3.12
$ docker pull php:7.3-apache
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
php                 7.3-alpine3.12      898191dd6734        8 days ago          74.3MB
php                 7.3-apache          4c443398a62c        8 days ago          410MB

说实话,完全没有可比性…

尽管Apache未包含在内,由于Alpine非常轻量化,即使加载了大量的软件包,也不可能达到buster镜像的程度。

我们将采用 php:7.3-alpine3.12 的镜像来进行。

确认一下 php:7.3-alpine3.12 的裸镜像缺少什么。

返回 Laravel 7.x 的安装要求。
https://readouble.com/laravel/7.x/ja/installation.html

如下所示。

    • PHP >= 7.2.5

 

    • BCMath PHP拡張

 

    • Ctype PHP拡張

 

    • Fileinfo PHP拡張

 

    • JSON PHP拡張

 

    • Mbstring PHP拡張

 

    • OpenSSL PHP拡張

 

    • PDO PHP拡張

 

    • Tokenizer PHP拡張

 

    XML PHP拡張

从基础镜像启动容器,然后逐步检查所需内容是否完善。

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
php                 7.3-alpine3.12      898191dd6734        8 days ago          74.3MB
php                 7.3-apache          4c443398a62c        8 days ago          410MB
$ docker run -it -d -p 8000:80 898191dd6734        // http://127.0.0.1:8000 でPC目視確認できるよう設定
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
b7a35b6625d7        d6096778d65d        "docker-php-entrypoi…"   7 seconds ago       Up 5 seconds        0.0.0.0:8000->80/tcp   wizardly_meitner

我在本地的电脑上执行了到这里为止的操作。
接下来我将登录到容器中,并调查一下库的状况。

$ docker exec -it b7a35b6625d7 /bin/sh

/ # php -m
[PHP Modules]
Core
ctype
curl
date
dom
fileinfo
filter
ftp
hash
iconv
json
libxml
mbstring
mysqlnd
openssl
pcre
PDO
pdo_sqlite
Phar
posix
readline
Reflection
session
SimpleXML
sodium
SPL
sqlite3
standard
tokenizer
xml
xmlreader
xmlwriter
zlib

[Zend Modules]

除了bcmath之外,似乎还有其他的方法… 但是光凭这些还不足以得出一个结论,需要更多的信息。

与使用yum或apt时不同,官方镜像是基于源代码构建的PHP,因此最终还是需要安装各个库。

为了确认这一点,最好使用php -i或者在WEB浏览器中设置phpinfo来进行考虑。

<?php
phpinfo();
?>
bcmath_support_enable.png

另外,我也确认了下列事项。

/ # date
Sat Jun 20 12:11:15 UTC 2020
/ # which composer        // 出力なし
/ # which npm             // 出力なし

考虑到时区为UTC并且在Laravel 7中缺少必要的命令,我们决定进行一些调整。此外,由于需要MySQL连接,还需要安装这些库。

实际编写的Dockerfile

FROM php:7.3-alpine3.12

# Document Root
RUN mkdir /application

# Package Install
RUN apk update && apk add --no-cache git tzdata apache2 npm \
    php7-common php7-apache2 php7-bcmath php7-ctype  php7-fileinfo php7-json \
    php7-mbstring php7-openssl php7-pdo php7-mbstring php7-tokenizer php7-xml \
    php7-session php7-pdo_mysql php7-mysqli \
  && cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime \
  && apk del tzdata

# Copy php.ini
COPY ./etc/php7/php.ini /etc/php7/

# Copy httpd.conf
COPY ./etc/apache2/httpd.conf /etc/apache2/

# Composer Install
RUN curl -sS https://getcomposer.org/installer | php -- \
  --install-dir=/usr/local/bin --filename=composer --version=1.10.6
    • –no-cache オプションについて :

 

    /var/cache/apk/ 配下のインストールキャッシュを自動で消してくれます。

在考虑可读性的前提下,我将上述内容总结如下:
假定要进行git克隆的应用程序将被放置在/document作为文档根目录。

需要仔细审查php.ini和httpd.conf的内容,并将其放置在Dockerfile相对路径中。此外,为了提高可读性并保持一致性,我们决定始终使用最新版本的composer命令,并指定版本。

我会在手边的电脑上进行构建,并确认内容。

$ docker build -t docker-image-base-laravel7x ./
$ docker images
REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
docker-image-base-laravel7x   latest              b239a1771f04        7 seconds ago       177MB

占用小于 177MB 的存储空间!

在我之前负责的项目中,由于最初的应用形象(CI形象)接近3GB,导致应用非常沉重。随后,在保持基本结构不变的情况下,尝试进行轻量化优化,成功地将其减少到大约1.5GB以下。

然而,这仍然是对本地开发过程有点重的感觉。
作为一个预期,如果CI映像小于1GB,那么有很大可能会有各种改善。

从这个前提来看,177MB是一个相当不错的数值。

コンテナに入って状況を確認します。

$ docker run -it -d b239a1771f04
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
d87924fc9320        b239a1771f04        "docker-php-entrypoi…"   8 seconds ago       Up 6 seconds                            epic_mccarthy
$ docker exec -it d87924fc9320 /bin/sh

我們將在貨櫃內檢查變更點。

/ # date
Sun Jun 21 19:02:24 JST 2020
/ # apk list | grep "php" | grep "installed"
php7-openssl-7.3.19-r0 x86_64 {php7} (PHP-3.01 BSD LGPL-2.0-or-later MIT Zend-2.0) [installed]
php7-tokenizer-7.3.19-r0 x86_64 {php7} (PHP-3.01 BSD LGPL-2.0-or-later MIT Zend-2.0) [installed]
php7-pdo_mysql-7.3.19-r0 x86_64 {php7} (PHP-3.01 BSD LGPL-2.0-or-later MIT Zend-2.0) [installed]
php7-common-7.3.19-r0 x86_64 {php7} (PHP-3.01 BSD LGPL-2.0-or-later MIT Zend-2.0) [installed]
php7-mysqlnd-7.3.19-r0 x86_64 {php7} (PHP-3.01 BSD LGPL-2.0-or-later MIT Zend-2.0) [installed]
php7-fileinfo-7.3.19-r0 x86_64 {php7} (PHP-3.01 BSD LGPL-2.0-or-later MIT Zend-2.0) [installed]
php7-mbstring-7.3.19-r0 x86_64 {php7} (PHP-3.01 BSD LGPL-2.0-or-later MIT Zend-2.0) [installed]
php7-session-7.3.19-r0 x86_64 {php7} (PHP-3.01 BSD LGPL-2.0-or-later MIT Zend-2.0) [installed]
php7-json-7.3.19-r0 x86_64 {php7} (PHP-3.01 BSD LGPL-2.0-or-later MIT Zend-2.0) [installed]
php7-xml-7.3.19-r0 x86_64 {php7} (PHP-3.01 BSD LGPL-2.0-or-later MIT Zend-2.0) [installed]
php7-apache2-7.3.19-r0 x86_64 {php7} (PHP-3.01 BSD LGPL-2.0-or-later MIT Zend-2.0) [installed]
php7-ctype-7.3.19-r0 x86_64 {php7} (PHP-3.01 BSD LGPL-2.0-or-later MIT Zend-2.0) [installed]
php7-bcmath-7.3.19-r0 x86_64 {php7} (PHP-3.01 BSD LGPL-2.0-or-later MIT Zend-2.0) [installed]
php7-pdo-7.3.19-r0 x86_64 {php7} (PHP-3.01 BSD LGPL-2.0-or-later MIT Zend-2.0) [installed]
php7-mysqli-7.3.19-r0 x86_64 {php7} (PHP-3.01 BSD LGPL-2.0-or-later MIT Zend-2.0) [installed]
/ # which composer
/usr/local/bin/composer
/ # composer -V
Composer version 1.10.6 2020-05-06 10:28:10
/ # which npm
/usr/bin/npm
/ # npm -v
6.14.4

已经顺利应用。

值得注意的是,我把 php7-session 包括在内。如果不安装这个包,将会出现以下错误日志,无法确认 Laravel 环境中的服务是否正常。

[Fri Jun 26 19:30:49.089145 2020] [php7:error] [pid 240] [client 172.17.0.1:42184] PHP Fatal error:  Interface 'SessionHandlerInterface' not found in /application/testapp/vendor/laravel/framework/src/Illuminate/Session/FileSessionHandler.php on line 10
[Fri Jun 26 19:30:49.394184 2020] [php7:error] [pid 236] [client 172.17.0.1:42204] PHP Fatal error:  Interface 'SessionHandlerInterface' not found in /application/testapp/vendor/laravel/framework/src/Illuminate/Session/FileSessionHandler.php on line 10

考虑在PECL上进行安装。

首先,我们考虑了以下关于memcached的方法。

# Install Memcached
RUN apk add --no-cache autoconf \
  libmemcached-dev zlib-dev \
  gcc g++ make \
&& pecl install memcached \
&& docker-php-ext-enable memcached

之前我提到 docker-php-ext-install 在结论上是无法使用的,原因是它无法将扩展集成到源代码安装的PHP中。

apk を使うことでこの部分をよきに計らってくれ、以下のようなiniファイルが生成されるのです。

/ # ls -la /etc/php7/conf.d/
total 72
drwxr-xr-x    1 root     root          4096 Jul  4 09:48 .
drwxr-xr-x    1 root     root          4096 Jul  3 10:49 ..
-rw-r--r--    1 root     root            20 Jun 12 21:27 00_bcmath.ini
-rw-r--r--    1 root     root            19 Jun 12 21:27 00_ctype.ini
-rw-r--r--    1 root     root            22 Jun 12 21:27 00_fileinfo.ini
-rw-r--r--    1 root     root            18 Jun 12 21:27 00_json.ini
-rw-r--r--    1 root     root            22 Jun 12 21:27 00_mbstring.ini
-rw-r--r--    1 root     root            21 Jun 12 21:27 00_openssl.ini
-rw-r--r--    1 root     root            17 Jun 12 21:27 00_pdo.ini
-rw-r--r--    1 root     root            21 Jun 12 21:27 00_session.ini
-rw-r--r--    1 root     root            23 Jun 12 21:27 00_tokenizer.ini
-rw-r--r--    1 root     root            17 Jun 12 21:27 00_xml.ini
-rw-r--r--    1 root     root            21 Jun 12 21:27 01_mysqlnd.ini
-rw-r--r--    1 root     root            20 Jun 12 21:27 02_mysqli.ini
-rw-r--r--    1 root     root            23 Jun 12 21:27 02_pdo_mysql.ini
-rw-r--r--    1 root     root            22 Jan 23 02:29 10_igbinary.ini

実際には pecl コマンドを使用してインストールするプラクティスを持つものも apk を経由しておよそインストール可能と見えます。

/ # apk search pecl
php7-pecl-imagick-dev-3.4.4-r3
php7-pecl-mailparse-3.1.0-r0
php7-pecl-imagick-3.4.4-r3
php7-pecl-uploadprogress-doc-1.1.3-r1
php7-pecl-amqp-1.10.2-r0
php7-pecl-yaml-2.1.0-r1
php7-pecl-memcache-4.0.5.2-r0
php7-pecl-psr-1.0.0-r0
php7-pecl-redis-5.2.2-r1
php7-pecl-ast-1.0.6-r0
php7-pecl-xdebug-2.9.6-r0
php7-pecl-couchbase-2.6.2-r0
php7-pecl-uploadprogress-1.1.3-r1
php7-pecl-apcu-5.1.18-r0
php7-pecl-timezonedb-2020.1-r0
php7-pecl-igbinary-3.1.2-r0
php7-pecl-uuid-1.1.0-r1
php7-pecl-gmagick-2.0.5_rc1-r5
php7-pecl-lzf-1.6.8-r0
php7-pecl-msgpack-2.1.0-r0
php7-pecl-vips-1.0.10-r1
php7-pecl-zmq-1.1.3-r6
php7-pear-7.3.19-r0
php7-pecl-mcrypt-1.0.3-r0
php7-pecl-xhprof-2.2.0-r0
php7-pecl-oauth-2.0.5-r0
php7-pecl-ssh2-1.2-r0
php7-pecl-memcached-3.1.5-r0
tesseract-ocr-4.1.1-r3
php7-pecl-protobuf-3.12.2-r0
php7-pecl-event-2.5.6-r0
php7-pecl-xhprof-assets-2.2.0-r0

総合的に考えると apk に寄せてしまい、 docker-php-ext-install/enable 系のコマンドは使わなくても良いと判断しました。

由于redis(phpredis) 的广泛应用,我指定了一个包含了它们以及memcached的Dockerfile,如下所示。

FROM php:7.3-alpine3.12

# Document Root
RUN mkdir /application

# Package Install
RUN apk update && apk add --no-cache git tzdata apache2 npm \
    php7-common php7-apache2 php7-bcmath php7-ctype  php7-fileinfo php7-json \
    php7-mbstring php7-openssl php7-pdo php7-mbstring php7-tokenizer php7-xml \
    php7-session php7-pdo_mysql php7-mysqli \
    php7-pecl-memcached php7-pecl-memcache php7-pecl-redis \
  && cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime \
  && apk del tzdata

# Copy php.ini
COPY ./etc/php7/php.ini /etc/php7/

# Copy httpd.conf
COPY ./etc/apache2/httpd.conf /etc/apache2/

# Composer Install
RUN curl -sS https://getcomposer.org/installer | php -- \
  --install-dir=/usr/local/bin --filename=composer --version=1.10.6

每个命令都有所省略,但图片尺寸如下所示。

$ docker images
REPOSITORY                                         TAG                 IMAGE ID            CREATED             SIZE
docker-image-base-laravel7x-cache                  latest              a928f55b49a6        40 seconds ago      180MB

180MB…
全くのところ、劇的に軽いです。
Dockerfileはこの作り方が正解なのではないかと考察します。

より高速なWEBのために

以前の担当案件では、イメージにPHPを高速化するためのアクセラレータ APCu, OPcache などが入っていました。

このあたりも案件は物理サーバから移植した構成であったため、(当初に) ほとんどそのまま入れたのだと思います。こうしたツールがコンテナにどの程度なじむかは、ちょっと注意・検証が必要かな…と思います。

由于我不打算深入探讨这些问题,所以是否需要进行确认将取决于环境和语言。

如果想要加快网络速度的话…

    • より一般的なキャッシュ (CDN, フレームワーク, DB, redisに寄せる… etc)

 

    • ボトルネックを見つけて対応 (モデル/SQLまわり, 処理ロジック… etc)

 

    ネットワークやサーバキャパシティプランニングの問題 (インフラ系)

などのセオリーがあるので、まず内部のキャッシュツールを導入するより、個人的には先にそういった原因調査から行う方がいいのではないかな…と。。
調査の過程で有用性が認められればあるいは、というのが本来の順序と考えます。

PHPに関しては言語自体以前よりはるかに高速化しているので、言語のバージョンとフレームワーク如何の組み合わせにも着目する必要があるでしょう。

最后

Dockerは検証や開発の環境作りにとても便利です。
また、Kubernetesなどでこれを運用することで、安定した本番環境を得ることもできます。

ただし、本番環境はとにかく軽くしておかないとアプリケーションの運用年数が長くなってきた時に、冒頭に書いたようなさまざまな不利益を被ることになります。さらに悪いことに、Dockerfileはコードであるためにサービスイン後にこれを変更することは (特に調整面で…) 手数も多く、当然危険も伴います。

コンテナアプリケーションのサービスイン時には、

    • より軽くシンプルなDockerfileの検討

 

    • 機能テストを網羅的に行うこと

 

    • キャパシティプランニングとスケーラビリティの調整

 

    現実的なシナリオを想定した負荷試験

进行适当平衡的同时,经过一定的时间仔细地执行会更明智。

精灵 ❤︎

广告
将在 10 秒后关闭
bannerAds