LoginSignup
5
3

More than 1 year has passed since last update.

DockerでLAMP + SSL +sSMTP+ node.js+gulp環境構築メモ(docker-syncも)

Last updated at Posted at 2019-01-22

概要

Qiita初投稿です。

*こちらの方法は古いので今使っている方法でのノートを近く公開する予定です。

WEBサイトの開発環境を簡単に用意できるようなテンプレートを作成した時の手順メモです。
年末にDocker-compose upで開発環境作れたらとても楽なのではとやり始めたのですが、DockerやLinuxの知識不足で手こずりました。
開発は主にMacで行なっているのでMac向けの設定で書いています。

SSLの設定は、自己認証局を一から作るととても面倒なので、「mkcert」を使うことにしました。
https://github.com/FiloSottile/mkcert

メール送信テストも行いたいですね。
Postfixとか設定大変です。
なのでこれも便利な「mailCatcher」を使います。
https://mailcatcher.me/

便利な時代になりましたね。

node.jsに関して。
最初、PHPのコンテナとNodeのコンテナを分けて構築する方法を考えていましたが、browser-sync関連で上手く行きませんでした。
仕方がないので PHPのコンテナにnode.jsをインストールする方法で無理やり解決させました。
(開発環境なのでこれでよしとしました)
また、Debianのatp-getでインストール出来るnode.jsは更新が滞っていて古かったりします。
nodebrew経由でのインストールでは最新も使えるそうなので、nodebrewをコンテナ内にインストールすることで解決させました。

参考)
https://shioleap.github.io/blog/Linux/Debian/install-nodejs-on-nodebrew/

追記2019/01/22 : なんかgulp.watchが遅いから調べた

さらに追記 20190123 : docker-syncで高速になって幸せに。

構成

root
└・dataディレクトリ
└・dockerディレクトリ
  └・web
   ├・Dockerfile
   ├・php.ini
   ├・ssl.conf
   └.ssmp.conf
└・public_html
  └・src
   └・scss
  ├・index.html
  ├・npm_nodule_list.txt
  └・npm.sh
├・.env
└・docker-compose.yml

自己認証局が作れるmkcertを使うための下準備

https://github.com/FiloSottile/mkcert
Homebrewを使ってインストールしていきます。
ちなみにWindowsではChocolateyでインストールが出来るそうです。

mkcertのインストール

Terminal
#Homebrewのインストール
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

#mkcertのインストール
$ brew install mkcert

自己認証局の設置

Terminal
#自己認証局のインストール
$ mkcert -install

開発用ドメインの登録

WEBサーバービルド用のDockerfileと同じディレクトリに移動してから実行すします。
今回は、localhostと開発マシンのローカルIPでの設定例にします。
例)

Terminal
$ cd ./docker/web/

$ mkcert localhost 192.168.XXX.1XXX

そうするとlocalhost+1-key.pemとlocalhost+1.pemとキーペアが作られます。

ちなみにmkcertは、複数のドメインやワイルドカードの設定なども出来るようです。

Terminal
#ドメイン固定の場合
$ mkcert local.hogehoge.dev
#ワイルドカードで全部のsub含める場合
$ mkcert *.hogehoge.dev
#自マシンのIPアドレスを使う場合
$ mkcert 192.168.3.100
#複数いっぺんにも可能
$ mkcert local.hogehoge.dev 192.168.3.100

Dockerfileの作成(WEBサーバー用)

公式のApache+PHPイーメージを使って、そこに必要なモジュールをインストールしていく方法にしました。
webディレクトリ内のDockerfileに読み込むイメージを指定します。

Dockerfile
FROM php:7.2-apache

PHPのセッティング+α

7.2-apacheのイメージではOSがDebianになる様子です。
以下インストールなどはDebianのやり方で記載していきます。

まずは、WEBサイトで使うであろうPHPの各モジュールのインストールと設定をします。
ついでにここで、ssmptとvimとcurlをインストールする設定も記述していきます。

PHP辺りの設定は、docker公式のWordpressのイメージなどを参考に追加しています。
案件ごとに本番サーバーの設定が変わると思われるので、モジュールは本番環境と同じにするとよいと思います。

Dockerfile
# install the PHP extensions we need
RUN set -ex; \
	\
	savedAptMark="$(apt-mark showmanual)"; \
	\
	apt-get update; \
	apt-get install -y --no-install-recommends \
		libwebp-dev \
    	libjpeg62-turbo-dev \
    	libpng-dev libxpm-dev \
    	libfreetype6-dev \
	; \
	#mail送信のみのパッケージのインストール
	apt-get install -y ssmtp mailutils; \
	#vimのインストール
	apt-get install -y vim; \
	#curlのインストール
	apt-get install curl; \
	#php gdの設定
	\
	docker-php-ext-configure gd \
	--with-webp-dir \
    --with-jpeg-dir \
    --with-png-dir \
    --with-zlib-dir \
    --with-xpm-dir \
    --with-freetype-dir \
    --enable-gd-native-ttf \
	--with-png-dir=/usr \
	--with-jpeg-dir=/usr; \
	docker-php-ext-install gd mysqli opcache zip; \
	\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
	apt-mark auto '.*' > /dev/null; \
	apt-mark manual $savedAptMark; \
	ldd "$(php -r 'echo ini_get("extension_dir");')"/*.so \
		| awk '/=>/ { print $3 }' \
		| sort -u \
		| xargs -r dpkg-query -S \
		| cut -d: -f1 \
		| sort -u \
		| xargs -rt apt-mark manual; \
	\
	apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
	rm -rf /var/lib/apt/lists/*

# set recommended PHP.ini settings
# see https://secure.php.net/manual/en/opcache.installation.php
RUN { \
		echo 'opcache.memory_consumption=128'; \
		echo 'opcache.interned_strings_buffer=8'; \
		echo 'opcache.max_accelerated_files=4000'; \
		echo 'opcache.revalidate_freq=2'; \
		echo 'opcache.fast_shutdown=1'; \
		echo 'opcache.enable_cli=1'; \
	} > /usr/local/etc/php/conf.d/opcache-recommended.ini

RUN a2enmod rewrite expires

ドキュメントルートの変更設定

本番環境によってはドキュメントルートが変わります。
デフォルトの/var/www/htmlのままでもいいのですが、合わせておくと何かと手間が省けるケースもあるので、ドキュメントルートを変更する設定も追加します。

Dockerfile
#change document root
#ドキュメントルートを変更する設定
#ここは任意のディレクトリを指定します(本番環境に合わせてもOK)
#docker-compose.ymlとssl.confにもDocument Rootを設定する箇所あり
ENV APACHE_DOCUMENT_ROOT /home/XXXX/public_html/www

RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf

VOLUME APACHE_DOCUMENT_ROOT

sSMTPの設定

sendmail pathをssmtpで使えるようにphp.iniにて設定

php.ini

[Date]
date.timezone = "Asia/Tokyo"

[Mail]
sendmail_path = "/usr/sbin/ssmtp -t"

mailcatcherがstmpのポート1025を使うので、ssmp.confにて設定

ssmp.conf

#
# Config file for sSMTP sendmail
#
mailhub=smtp:1025
FromLineOverride=YES

SSLの設定

ssl.confの設定

ssl.conf
#SSLのキーペアを設定する
SSLCertificateFile  /etc/apache2/ssl_keys/localhost+1.pem
SSLCertificateKeyFile  /etc/apache2/ssl_keys/localhost+1-key.pem

Dockerfileに追加

Dockerfile

#SSL設定
ADD ./ssl.conf /etc/apache2/sites-available/ssl.conf
ADD ./localhost+2-key.pem /etc/apache2/ssl_keys/localhost+2-key.pem
ADD ./localhost+2.pem /etc/apache2/ssl_keys/localhost+2.pem

nodebrewのインストール設定

参考URL
https://shioleap.github.io/blog/Linux/Debian/install-nodejs-on-nodebrew/

nodebrewインストール時に以下のメッセージが表示されるそうです。
参考URLの言う通りにコマンドを打つときに面倒なので、この設定をしたいと思いました。

Dockerfileに追加

Dockerfile
#nodebrewのインストール
RUN curl -L git.io/nodebrew | perl - setup
RUN echo 'export PATH="$HOME/.nodebrew/current/bin:$PATH"' >> ~/.bashrc && . ~/.bashrc

Apacheの起動設定

最後にDockerfileにApacheをフォアグランドで起動する命令を書きます。

Dockerfile
CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]

docker-compose.ymlファイルの作成

ざっくりこんな感じで設定

version: '2'
services:
  db:
    image: mysql:5.7
    # ./data/db(ホストOS)にデータが保持される
    volumes:
      - "./data/db:/var/lib/mysql"
    env_file: .env
  httpd:
    build: ./docker/web
    depends_on:
      - db
    ports:
      - "80:80"
      - "443:443"
      - "3000:3000"#browser-sync用
      - "3001:3001"#browser-sync用
    privileged: true
    #ドキュメントルートを変更する設定
    #左はローカルマシンのディレクトリ
    #右はコンテナ内のディレクトリ
    #ここは任意のディレクトリを指定します(本番環境に合わせてもOK)
    #Dockerfileとssl.confにもDocument Rootを設定する箇所あり
    volumes:
       - "./public_html:/home/XXXX/public_html/www"
  smtp:
    image: schickling/mailcatcher
    ports:
      - "1080:1080"#MailCatcher
      - "1025:1025"#smtp用
  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    env_file: .env
    links:
      - db
    ports:
      - 8080:80
    volumes: 
      - "./phpmyadmin/sessions:/sessions"

.envはデータベース用の設定ファイル

MYSQL_RANDOM_ROOT_PASSWORD=yes
MYSQL_DATABASE=[データベースの名前]
MYSQL_USER=[ユーザー]
MYSQL_PASSWORD=[パスワード]

docker-syncで高速になって幸せに - docker-syncの設定

  • docker for macはホスト側のvolumeをマウントしていると劇的に遅い
  • docker toolboxをゴニョゴニョすればできるらしい。
  • docke-syncを使うと劇速になるらしい。しかも割と簡単。

ということで、docker-syncを採用してみました。
参考URL
https://qiita.com/Satoshi_Numasawa/items/278a143aa41735e1b0da
https://github.com/EugenMayer/docker-sync
https://github.com/EugenMayer/homebrew-dockersync

まずはインストールします。

terminal
$ sudo gem install docker-sync
brew install eugenmayer/dockersync/unox
brew install fswatch unison rsync

Macに初めから入っているrubyだと権限のからみでsudoでインストールしないとpermission deniedで怒られることがあります。
*sudoでインストールしても問題なく動きました。

docker-sync.ymlにてシンクするホストのディレクトリと同期方法を指定する

「sync_strategy」にて同期の方向を決めます。

  • rsync : ホスト→コンテナへの同期
  • unison : 双方向の同期
docker-sync.yml

version: '2'

syncs:
  sync-volume:
    src: './public_html'
    sync_strategy: 'unison'

docker-compose-dev.yml

docker-sync.ymlの設定内容をdocker-compose.ymlを上書き設定するためのファイルの設定

docker-compose-dev.yml
version: '2'

volumes:
  sync-volume:
    external: true

services:
  httpd:
    volumes:
      - sync-volume:/home/webmaster/public_html/www

まずは、imageをBuildします

Terminal
$ docker-compose pull
$ docker-compose build --no-cache

docker-syncを起動してからコンテナを作成します

Terminal
$ docker-sync start
$ docker-compose -f ./docker-compose.yml -f ./docker-compose-dev.yml up -d

これでやっとLAMP+ssl+メールテスト環境の出来上がりました。

mailCatcherでメール内容を確認する場合は、 "http://localhost:1080" とすると確認できます。
参考URL
https://mailcatcher.me/

node.jsのインストール

全部Dockerfileに書いてしまおうかと思っていましが、開発の環境によって色々かわるかもと思ったのでとりあえず手動でいいかなと。
あとあまり突っ込みすぎると up --buildの時に時間がかかりすぎるかななど。
*単に面倒になってきただけかも。

もしDockerfileに記述してup --buildでnode.jsのインストールまで行いたい場合はこちらが参考になるかと思います。

https://qiita.com/kenshiroh/items/f8702086e3ae29cfc350
OSが違いますが、最後の2行が参考になります。

コンテナへのログイン

コンテナへのログインは、

$ docker exec -it {コンテナ名} /bin/bash

でできます。

例として

#まずコンテナ名を調べます
$ docker-compose ps
        Name                       Command               State                                           Ports
-------------------------------------------------------------------------------------------------------------------------------------------------------
php-node_db_1           docker-entrypoint.sh mysqld      Up      3306/tcp, 33060/tcp
php-node_httpd_1        docker-php-entrypoint /usr ...   Up      0.0.0.0:3000->3000/tcp, 0.0.0.0:3001->3001/tcp, 0.0.0.0:443->443/tcp,
                                                                 0.0.0.0:80->80/tcp
php-node_phpmyadmin_1   /run.sh supervisord -n -j  ...   Up      0.0.0.0:8080->80/tcp, 9000/tcp
php-node_smtp_1         mailcatcher --no-quit --fo ...   Up      0.0.0.0:1025->1025/tcp, 0.0.0.0:1080->1080/tcp
#↑こんなのでます。
$ docker exec -it php-node_httpd_1 /bin/bash #return

ログインしたらディレクトリは初期設定の/var/www/htmlになっています。

まずはnode.jsのリモートの一覧を表示

$ nodebrew ls-remote

使いたいバージョンのnode.jsをインストール

#v10.15.0での例
$ nodebrew install-binary v10.15.0
# 10.15.0を使うように指示
$ nodebrew use v10.15.0

Gulpの設定

作業ディレクトリでnpmの初期化

#もし設定でドキュメントルートを変更していましたら、そちらに移動します。
$ cd /home/XXXX/public_html/www
$ npm init -y

package.jsonにrepositoryのエラーが出ないようにするために記述を追加

$ vi package.json
{
  "name": "www",
  "version": "1.0.0",
  "main": "gulpfile.js",
  "dependencies": {},
  "private": true,←これ
  "devDependencies": {
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "keywords": [],
  "description": ""
}

Gulpをインストールする

$ npm istall —save-dev gulp

gulpへのパスが通らない場合があるので、パスを通す

$ npm link gulp
#これ一発でOK!簡単!

その他のパッケージもインストールする

npm install —save-dev gulp-sass

などなど。

インストールの時にこんなエラーが出ます。

npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.0.0 (node_modules/chokidar/node_modules/fsevents):

これは、MacOS限定のモジュールだそうで、このエラーはそれほど気にしなくていいかもしれません。
もし気になるようでしたら、

npm install --no-optional XXXX

と--no-optionalをつけるといいそうです。
*個人的にはこのエラーは気にならなかったので、試してみてないです。

参考URL
https://mimirswell.ggnet.co.jp/blog-221

####一発でパッケージをインストールする方法

シェルスクリプトを書いて一発でインストールしちゃいます。
npm.shに以下を記述します。

#!/bin/sh

for i in `cat npm_module_list.txt`
do
  npm install --save-dev $i
done

npm_module_list.txtファイルに必要なパッケージを書いていきます。
例)

gulp
gulp-sass
browser-sync
gulp-notify
gulp-plumber
gulp-sourcemaps
gulp-group-css-media-queries
gulp-autoprefixer
gulp-clean-css
gulp-uglify-es
gulp-rename
gulp-inline-source
$ bash npm.sh

browser-syncについて

proxyの設定でlocalhostを指定したら上手くいきました。
あとはdocker-compose.ymlにてポート3000と3001の設定をしてあればOK

gulp.task('browser-sync',function(done){//browser-syncのタスク設定
   browserSync({
       proxy:"localhost",
	   open: false
   });
   done();
});

gulp.watchについて

Gulpのその他の設定は参考文献がたくさんあるので、そちらを参照してgulpfile.jsを作っていけば良いかと思います。
ただDockerコンテナのDebianなどでbrowser-syncを使うと、指定したファイルが更新しても、browser-syncの方で認識しないようです。

その場合はポーリングの設定をするといいとの情報がありました。
具体的には、gulpfile.jsで記述する際に

gulp.watch(paths.scss + '**/*.scss',{ usePolling: true }, gulp.series('scss'));

とするといいようです。

参考URL
https://github.com/floatdrop/gulp-watch/issues/213
https://www.kimurak.net/wordpress/angularjs/2372/

これで、快適開発環境が作れました!!

追記 : 思ったらなんか"gulp.watchが遅い!!!ので調べた

https://blog.hanhans.net/2017/05/23/docker-for-mac-slow/

ホスト側のディレクトリのマウントに関して前から問題が出ていたんですね。

なんか方法があるようですが、ちょっとハードルが高い。
しばらくはコンテナ内でgulp.watchは避けた方がいいかも…。
せっかくまとめましたが、node.jsをコンテナに入れてという方法はしばらく封印します。

docker-syncの方法を追記しました。

とても快適です。

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3