docker-composeでcentosベースのlaravel開発環境を構築してみる

f:id:miya15:20180909171239p:plain

前提条件

  • ホスト側でdockerとdocker-composeが使えること
  • ゲスト側OSはcentos7
  • フレームワークはlaravel5.6
  • データベースはmysql5.7

ホスト側ファイル構成

/laraveldev
 /web
  /Dockerfile
 /docker-compose.yml

web用コンテナイメージの準備

$ mkdir laraveldev
$ mkdir laraveldev/web
$ vim laraveldev/web/Dockerfile
FROM centos:7

# apacheとphp7.2のインストール
RUN yum -y update
RUN yum -y install epel-release unzip vim git
RUN yum -y install http://rpms.remirepo.net/enterprise/remi-release-7.rpm
RUN yum -y --enablerepo=remi-php72 install php php-devel php-mbstring php-mysql php-gd php-pdo php-pear php-process php-soap php-xml php-bcmath php-pecl-zip
RUN yum -y install httpd-devel

# composerのインストール
WORKDIR /tmp
RUN curl -sS https://getcomposer.org/installer | php
RUN mv composer.phar /usr/local/bin/composer
RUN useradd developer
RUN groupadd web
RUN gpasswd -a apache web
RUN gpasswd -a developer web
RUN chown -R apache:web /var/www
RUN chmod g+ws -R /var/www

# composerでlaravelのインストール
USER developer
RUN composer global require "laravel/installer"
RUN echo 'PATH=$PATH:$HOME/.composer/vendor/bin' >> ~/.bashrc
RUN source ~/.bash_profile

# プロジェクトの作成
WORKDIR /var/www
RUN composer create-project --prefer-dist laravel/laravel mysite "5.6.*"

USER root
RUN chmod g+ws -R /var/www/mysite

# apacheの設定変更
RUN sed -i -e 's#DocumentRoot "/var/www/html"#DocumentRoot "/var/www/mysite/public"#' /etc/httpd/conf/httpd.conf
RUN echo $'\n\
<Directory "/var/www/mysite/public">\n\
    AllowOverride All\n\
    Require all granted\n\
</Directory>\n\
' >> /etc/httpd/conf/httpd.conf
RUN systemctl enable httpd

# データベースの設定
RUN sed -i -e 's/DB_HOST=127.0.0.1/DB_HOST=db/' \
-e 's/DB_DATABASE=homestead/DB_DATABASE=dbmysite/' \
-e 's/DB_USERNAME=homestead/DB_USERNAME=umysite/' \
-e 's/DB_PASSWORD=secret/DB_PASSWORD=password/' \
/var/www/mysite/.env
RUN sed -i -e "s/env('DB_HOST', '127.0.0.1')/env('DB_HOST', 'db')/" \
-e "s/env('DB_DATABASE', 'forge')/env('DB_DATABASE', 'dbmysite')/" \
-e "s/env('DB_USERNAME', 'forge')/env('DB_USERNAME', 'umysite')/" \
-e "s/env('DB_PASSWORD', '')/env('DB_PASSWORD', 'password')/" \
/var/www/mysite/config/database.php

CMD ["/sbin/init"]

docker-compose化

$ vim laraveldev/docker-compose.yml
version: '3.3'

services:
  db:
    image: mysql:5.7
    volumes:
      - db_data:/var/lib/mysql
    ports:
      - 3306:3306
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: dbmysite
      MYSQL_USER: umysite
      MYSQL_PASSWORD: password

  web:
    depends_on:
      - db
    build: ./web
    volumes:
      - web_data:/var/www/mysite
    ports:
      - 80:80
    restart: always

volumes:
  db_data:
  web_data:

ビルドと起動

$ cd laraveldev
$ docker-compose build
$ docker-compose up -d

おまけ

  • コンテナに入る
    • $ docker exec -it laraveldev_web_1 /bin/bash
  • mysiteのホスト側ディレクト
    • $ ls /var/lib/docker/volumes/laraveldev_web_data/_data/
  • dbのホスト側ディレクト
    • $ ls /var/lib/docker/volumes/laraveldev_db_data/_data/

jenkinsのdockerイメージからホストのdockerが使えるようにするDockerfile(docker in docker)

f:id:miya15:20180908164903p:plain

jenkinsはdockerイメージが公式に公開されているので使いやすいですが、jenkins自体がコンテナとして動くのでホスト側のdockerコマンドを実行させるには多少の小細工が必要です。これはdocker in dockerと呼ばれているらしく、このキーワードで検索すれば比較的目的の記事が見つかりやすいと思います。
今回はjenkinsのイメージを使っていますがdocker in docker自体は他のイメージでも概念は一緒です。

Dockerfileの例

公式のjenkinsイメージを使ってdockerとdocker-composeをインストールします。

  • ポイント
    • ユーザー切り替えを行ってインストールを進めている点(最後にjenkinsに戻しています)
    • jenkinsユーザーにdockerコマンドのsudo権を与えている点
FROM jenkins:latest
USER root

RUN apt-get update -y
RUN apt-get install -y \
     apt-transport-https \
     ca-certificates \
     curl \
     gnupg2 \
     software-properties-common
RUN curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg | apt-key add -
RUN add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") \
   $(lsb_release -cs) \
   stable"
RUN apt-get update
RUN apt-get install -y docker-ce

RUN curl -L https://github.com/docker/compose/releases/download/1.16.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
RUN chmod +x /usr/local/bin/docker-compose

RUN echo "jenkins ALL=(root) NOPASSWD: /usr/bin/docker" >> /etc/sudoers

USER jenkins

ビルドの例

$ sudo docker build -t jenkinsdid .

実行時の例

  • ホスト側のdocker.sockをコンテナ側にバインドしている点がポイント
$ sudo docker run -d -p 8080:8080 -v /var/run/docker.sock:/var/run/docker.sock jenkinsdid

jenkinsでdockerイメージをビルドする例

jenkinsでDockerfileをビルドして、既にコンテナがあったら削除して、新たにコンテナを作る例
下記をビルドの「シェルの実行」に入れる

sudo docker ps -a
sudo docker build -t dockertest $WORKSPACE
if sudo docker ps -a | grep webtestwork -n; then sudo docker stop webtestwork; fi
sudo docker run -d --rm --name webtestwork dockertest /sbin/init
  • 説明
    • 1行目:現在動いているdockerコンテナを表示(デバッグ目的で表示しているだけで実動作には無くても問題無い)
    • 2行目:ワークスペースにDockerfileがある前提でタグ「dockertest」を付けてビルド
    • 3行目:コンテナ名「webtestwork」が付いているコンテナが存在したら停止(停止したら削除されるrmオプションが付いている想定)
    • 4行目:コンテナ名「webtestwork」でイメージ名「dockertest」からコンテナを生成(停止したら削除されるrmオプション付き)

dockerのpushでRetryingになる時の確認事項(private registry)

その1:SELinuxに制限されている場合

SELinuxを無効化してみる

$ sudo vi /etc/selinux/config

変更箇所

SELINUX=enforcing
 ↓
SELINUX=disabled

$ sudo reboot

SELinuxをONにしたままでも出来るかもしれませんが…

dockerのコンテナ内から外に接続できない時の確認事項

dockerのコンテナ内から外にネットワーク接続が出来なくなった時の確認事項を挙げていきます。

  • ホスト側でpingが通るか確認する
    • これがダメな場合はまずホスト側の設定を見直す必要がある
  • 前は繋がっており設定は変えてない場合、dockerサービスを上げなおす
    • コンテナ内のデータを永続化していない場合は上げなおす前にコミットしたり退避したりするのを忘れないように

※事例を見つけたら追記していきます

jenkinsの公式dockerイメージを拡張する際のメモ

jenkinsの公式dockerイメージをDockerfileで独自に拡張したいと思ったのですが、デフォルトのユーザーがjenkinsになっていてパッケージのインストールなどが行えなくて困ったのでそのメモです。

docker run する場合

$ docker run -u root -d -p 8080:8080 jenkins

Dockerfile を書く場合

FROM jenkins:latest
USER root

RUN apt-get update -y
 :

USER jenkins

メール送信者側のgmail迷惑メール対策

gmail宛てにメールを送ってスパム扱いされました・・・。開発用途で使っていたので色々と設定を怠っていたのは間違いありません。

googleが提供している手軽に使えるDNS確認ツールについて紹介します。MXレコード設定におけるよくある間違いをチェックできます。簡単な説明も付いているので至れり尽くせりです。

Check MX: Check MX and SPF Records.

f:id:miya15:20180806111718p:plain

 

SPFDKIMといった一般的な設定についてもチェックできますのでまずはここの指摘を対応していくのが第一歩になるかと思います。

 転送する予定が無ければ取り急ぎSPFだけでも設定しておくのが良いでしょう。それで大丈夫になる保証はありませんがいくぶんかマシになります。転送する予定がある場合はDKIMにしないと難しいかもしれません。SPFで転送元も許可する事はできますが、メールサービスを提供している会社そのものを許可する必要が出てきたら本末転倒になります(自身以外からのメールを信頼させてしまう可能性が出てくるので)。

ちょっと面倒でもDKIMの方が後々良いかもしれませんね。

awsのroute53の任意のhostedzoneの操作を許可したい

f:id:miya15:20180803160905p:plainawsのroute53で特定のhostedzoneだけをユーザーに触らせたい、という制御をIAMポリシーでやってみたいと思います。
まずはサービスから「IAM」を選びましょう。
左側のメニューから「ユーザー」でも「グループ」でも構いませんが、対象を選んで「インラインポリシーの追加」をクリックします。

JSONで下記のように権限を設定すればOKです。
途中にある「(許可したいHosted Zone ID)」の部分に文字通りのIDを入れてください(route53のHosted zonesの一覧画面の右端のカラムにあります)。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1",
            "Effect": "Allow",
            "Action": [
                "route53:ListResourceRecordSets",
                "route53:GetHostedZone",
                "route53:ChangeResourceRecordSets"
            ],
            "Resource": [
                "arn:aws:route53:::hostedzone/(許可したいHosted Zone ID)"
            ]
        },
        {
            "Sid": "Stmt2",
            "Effect": "Allow",
            "Action": [
                "route53:ListHostedZones",
                "route53:GetHostedZoneCount"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}