オープンソースのSNSをDockerで動かしてみたら懐かしすぎた
こんにちは、たかぴーです。
このエントリは、GMOペパボエンジニア Advent Calendar 2020 - Adventarの8日目の記事です。7日目はしばっちさんの「AWSでDNSをRoute53を使わずに構築する」でした。
社内のPHPアプリケーションをDocker化するにあたりどういった流れで構築していくのか、自分はこうやっているよ!というのを書いていこうと思ったのですが、社内のアプリケーションの設定やソースコードは表に出す訳にはいかないので、今回は代わりにOpenPNEという、PHP製のオープンソースなSNSをDocker化し構築の流れを書いていきます。
今回は最低限動かすことが目的なので、ローカルで動くところまでをゴールとします。
1. まずは、ざっくり動かしてみる
まずは細かいことは気にせず、ざっくり動かしていきます。
情報を集める
最新版(12/8時点)のOpenPNEのセットアップ手順をの通りにやれば良さそうです。
推奨構成はこんな感じ
OS: Debian jessie Apache 2.4.10 以降 PHP: PHP 7 以降 DB MySQL 5.5.53以降
いわゆるLAMP環境ってやつですね。 Docker Hubの公式イメージを使って作れそうです。
docker-composeを使って大枠を作る
最終的には、docker-composeがなくてもイメージ単体で動作させる予定ですが、 イメージ構築時は、設定をyamlに追加しながら作業できるので、個人的にはdocker-composeを使いながら構築するのがやりやすいです。
こんな感じで大枠を作成
version: '3' services: app: build: ./ db: image: mysql:5.7.32
FROM php:7.4.10-apache-buster
php:7.4.10-apacheで、jessieのイメージはなかったので、busterを使いました。(多分動くはず)
基本的に野良イメージは使わず、Officialなイメージを使うようにしています。
ライブラリを追加
引き続き、セットアップ手順を参考に必要なライブラリを追加していきます。
Dockerfileは後ほどきれいにするので、まずは雑にライブラリをインストールしていきます。
Dockerfileは上から各命令ごと順番にキャッシュされます。 そのため、構築時に上の方に記述されている命令を変更すると、それ以下はキャッシュが効かなくなるため、一気にインストールせずキャッシュを効かせながらインストールしています。
FROM php:7.4.10-apache-buster RUN apt update && apt -y upgrade RUN apt install -y libonig-dev RUN docker-php-ext-install mbstring RUN apt install -y libxml2-dev RUN docker-php-ext-install xml RUN docker-php-ext-install pdo_mysql RUN docker-php-ext-install json RUN apt -y install zlib1g-dev RUN apt -y install libpng-dev RUN apt -y install exif RUN apt -y install mcrypt RUN pecl install apcu RUN docker-php-ext-enable apcu RUN pecl install xdebug RUN docker-php-ext-enable xdebug RUN a2enmod rewrite RUN docker-php-ext-install exif
ソースコード・設定ファイルをマウント
docker-compose側で、ソースコードとOpenPNEの設定ファイルをマウントするようにします。 また、ここには出していないですがphp.ini, apache2.confの内容もいい感じに設定しています。
volumes: - ./src:/var/www/html - ./config/OpenPNE.yml:/var/www/html/config/OpenPNE.yml - ./config/ProjectConfiguration.class.php:/var/www/html/config/ProjectConfiguration.class.php - ./config/apache2.conf:/etc/apache2/apache2.conf - ./config/php.ini:/usr/local/etc/php/php.ini
個人的に、設定ファイルはconf.dなどメインのファイルにインクルードするような場所に置くと使用するイメージの設定によって設定内容が変わってくるため、conf.dなどのメインに設定にインクルードするような箇所にはマウントせず、メインのファイルのみ書き換えインクルードさせないようにするのが好みです。(が、みなさんどうやっているのだろう??)
初期化する
初期設定では、コマンドを叩きテーブルを初期化する必要があるようなので、mysqlのDBにユーザ・パスワード等の設定を追加し、実行します。
DBの設定を追加
db: image: mysql:5.7.32 volumes: - data_volume:/var/lib/mysql environment: TZ: Asia/Tokyo LANG: ja_JP.UTF-8 MYSQL_DATABASE: openpne MYSQL_USER: openpne_user MYSQL_PASSWORD: openpne_password MYSQL_RANDOM_ROOT_PASSWORD: "yes" volumes: data_volume:
初期化コマンドを実行!
docker-compose run --rm app bash -c "./symfony openpne:fast-install --dbms=mysql --dbuser=openpne_user --dbpassword=openpne_password --dbhost=db --dbport=3306 --dbname=openpne"
>> installer installation is completed!
と出力されたので上手くいったっぽい。
動かす!
docker-compose up して動かします!
おお、なんかすごくm○xiっぽい。構築がおわったらゆっくり見ていきます。
とりあえず、それっぽいコミュニティを設定しときました。
動かない箇所の修正
ポチポチ動かしてみると画像のアップロードが上手く行きませんでした。 エラーログやXdebugなどでデバッグで確認していきます。
ちなみに、DockerへのXdebug導入はこんな感じ
今回は、拡張モジュールであるGDが漏れていたようなので追加しました。
RUN apt-get install -y libfreetype6-dev libjpeg-dev RUN docker-php-ext-configure gd --with-jpeg=/usr/include/ --with-freetype=/usr/include/ RUN docker-php-ext-install -j$(nproc) gd
これで一通り動きました!
2. 設定を見直す
Dockerfileを整理する
キャッシュが効くようにババっと書いていってしまいましたが、 見た目も悪いですし、イメージのサイズも大きくなってしまうので整理していきます。
FROM php:7.4.10-apache-buster RUN apt update && apt -y upgrade && apt install -y --no-install-recommends \ exif \ libfreetype6-dev \ libjpeg-dev \ libonig-dev \ libpng-dev \ libxml2-dev \ mcrypt \ zlib1g-dev \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* RUN pecl install apcu && docker-php-ext-enable apcu RUN docker-php-ext-install -j$(nproc) \ exif \ json \ mbstring \ pdo_mysql \ xml RUN docker-php-ext-configure gd --with-jpeg=/usr/include/ --with-freetype=/usr/include/ \ && docker-php-ext-install -j$(nproc) gd RUN a2enmod rewrite
こんな感じで整理しましたが、整理した以外にも上記の設定はこんなことを意識しています。
apt updateと一緒にapt installする
apt installをする際に古いパッケージ情報をキャッシュしたままだと、更新できないケースがありますので、それを避けるために、apt update apt installまとめています。 これにより、パッケージを追加したときにすべて新しいパッケージ情報で、更新されるようになります。
--no-install-recommendsを追加する
必須ではないパッケージが入ってくることを防いでいます。 https://manpages.debian.org/unstable/apt/apt-get.8.ja.html#%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3
キャッシュを削除する
&& apt-get clean \ && rm -rf /var/lib/apt/lists/*
aptキャッシュをクリーンにし、/var/lib/apt/lits を削除することで、イメージのサイズを減らしています。
Dockerfile のベストプラクティス — Docker-docs-ja 1.9.0b ドキュメント
docker-composeに設定した値をDockerfileに寄せる
今回はDockerイメージ単体でも動作するようにしたいので、ソースコード・設定ファイルをDockerfileに移動させます。
COPY ./src /var/www/html COPY ./config/OpenPNE.yml ./config/ProjectConfiguration.class.php /var/www/html/config/ COPY ./config/apache2.conf /etc/apache2/apache2.conf COPY ./config/php.ini /usr/local/etc/php/php.ini
コピーする命令はCOPYの他にADDがありますが、ADDはローカル上でのtar展開や、リモートURLのサポートなど多くの機能を持っていて混乱の元なので、明確にCOPY以外の機能を使いたいとき以外は使わないようにしています。
こちらでもそう言っていますね。
Dockerfile のベストプラクティス — Docker-docs-ja 1.9.0b ドキュメント
その他、細かな設定を追加
WORKDIR,、EXPOSE、タイムゾーン、言語設定を追加します。
ENV TZ=Asia/Tokyo ENV LANG=ja_JP.UTF-8 WORKDIR /var/www/html EXPOSE 80
また、先に、DBが起動して欲しいので、depends_on
を追加します。
depends_on: - db
3.ちょっとだけ、セキュアにする
今回はローカル環境でしか動かさないのですが、もし今後公開した環境で稼働させたくなったときにスムーズに移行できるよう、今回少しだけセキュリティ設定はしておきます。
アプリケーションのパーミッションに設定する
ソースコードを置いているディレクトリは最低限必要な権限のみを付与するようにします。
RUN chown -R www-data:www-data /var/www/html \ && chmod -R 400 /var/www/html \ && find /var/www/html -type d | xargs -I{} chmod 500 {} \ && chmod 700 /var/www/html/log /var/www/html/cache
ReadOnlyで起動する
docker-compose.ymlに read_only: true
を追加します。
書き込みが必要なディレクトリは次のように匿名ボリュームをマウントすることで書き込めるようにします。
read_only: true volumes: - /var/www/html/log - /var/run/apache2/ - /tmp
こちらに関しては先日記事を書きましたので良かったらご覧ください
dockerignoreを設定する
イメージに含める必要のないファイルは.dockerignoreで除外しました。
4. 最終チェック
--no-cache
オプションを利用して念の為キャッシュを使わず最初からビルドをし直して問題ないか確認します。
COMPOSE_DOCKER_CLI_BUILD=1 docker-compose build --no-cache
※COMPOSE_DOCKER_CLI_BUILD=1を設定することで、BuildKitを使って高速にビルドする様にしています。BuildKitについてはこちら
いろいろイジってみる
どうやら、インストール直後はプロフィールとコミュニティ機能くらいしか無いようなのですが、プラグインを追加することで、タイムラインや日記、あしあと機能などを追加ができるようです。
各プラグインはこのページの各プラグインをクリックしたあとに表示されるコマンドを入力することで追加できるようです。
プラグインを追加していった結果こんな見た目になりました!! なんかすごく大学生の頃を思い出すような懐かしい見た目になった!!!
本家(UIの参考になったであろうサービス)の方もたまにはログインしてみようと思います。
まとめ
今回は、OpenPNEを使ったローカル環境を構築してみましたが、業務で使用している開発環境も大体同じような流れで構築をしています。もしこうすると良いよ!などアドバイスなどがあればコメントいただけると嬉しいです。
Twitterやっているので、良かったらマイミク申請フォローお願いします。
明日9日目は、mochikoさんです〜