DockerでLAMP&Redis環境を構築しながら、色々使い方を覚える（備忘録）

もし不明なところや、間違いとかがあればご指摘頂けると幸いです。

## やること

```
php-fpm(php7.4)
centos7
apache2.4
mariadb
phpMyadmin
nodejs (with Gulp)
redis
```

- 上記の環境をDockerで構成する
- Dockerfileと各環境の設定ファイルを構成する
- docker-compose.ymlを構成する
- docker-composeで各環境のコンテナーを起動し内部状態を確認する
- Laravel上で、MariaDBとRedisのコネクションを確認する

## 全体ソースコード
https://github.com/genie-oh/docker-lamp

## 参考にした記事&Github レポジトリ
https://qiita.com/temori1919/items/487d68a19ca1de1a63c8
https://github.com/temori1919/docker-lamp

## 基本レファレンス
Dockerfileのレファレンス
https://docs.docker.com/engine/reference/builder/

Docker Composeのレファレンス
https://docs.docker.com/compose/compose-file/

## 1. Docker構成

### 1) web構成 (centos & apache)
公式 dockerhub
https://hub.docker.com/_/centos

#### 構造
```
docker-lamp/
`-- web
|   |-- Dockerfile
|   |-- docker.conf     # Copy to /etc/httpd/conf.d
|   `-- logs            # for apache log
```

#### web/docker.conf
Apacheのconfig。
主にバーチャルホスト関連設定を定義する。
phpの処理はphp-fpmに任せるのでproxy設定をしておく。

```
# rootdomain
<VirtualHost *:443>
...
    ServerName lamplocal.me
    VirtualDocumentRoot /var/www/html/home_root/public
...
</VirtualHost>

# subdomain. phpの動作が可能
<VirtualHost *:443>
...
    ServerName lamplocal.me
    ServerAlias *.lamplocal.me
    VirtualDocumentRoot /var/www/html/home_sub/%1/public

    <FilesMatch \.php$>
        SetHandler "proxy:fcgi://php:9000"
    </FilesMatch>
...
</VirtualHost>
```

#### web/Dockerfile
apache.2.4のインストール
任意のSSL認証書を作成
docker.confをコンテナーにコピー

```docker
# centos:7のイメージを元にコンテナーを作成
FROM centos:7  

# 指定のコマンド実行
RUN ... 

# ホストシステムからコンテナーにファイルをコピー
COPY docker.conf /etc/httpd/conf.d/docker.conf 

# コンテナー起動時に実行するコマンド
CMD ["/usr/sbin/httpd", "-DFOREGROUND"]
```

### 2) php構成 (php-fpm 7.4)
公式 dockerhub
https://hub.docker.com/_/php

#### 構造
```
docker-lamp/
|-- php
|   |-- Dockerfile
|   |-- logs            # For xdebug.log
|   `-- xdebug.ini      # Copy to /usr/local/etc/php/conf.d
```

#### xdebug.ini
xdebugの基本設定の他に、xdebug.logを残すように設定

```
xdebug.remote_log=/var/log/xdebug/xdebug.log
```

#### Dockerfile

```docker
# php:7.4-fpmのイメージを元にコンテナーを作成
FROM php:7.4-fpm

# phpのイメージで提供するユティリティの`docker-php-ext-install`,`docker-php-ext-enable`でPHP EXTENSTIONを設置
RUN pecl install xdebug-2.8.1 \
	&& docker-php-ext-enable xdebug \
	&& docker-php-ext-install bcmath pdo_mysql

# ホストシステムからコンテナーにファイルをコピー
COPY ./xdebug.ini $PHP_INI_DIR/conf.d/

# 外部イメージから、コンテナーにファイルをコピー
# 公式composerイメージから、phpコンテナーにcomposerを設置
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
```

### 3) mariaDB構成
公式 dockerhub
https://hub.docker.com/_/mariadb

#### 構造

```
docker-lamp/
|-- db
|   |-- Dockerfile
|   |-- logs            # For slow query log
|   `-- my.cnf          # Copy to /etc/mysql/conf.d
```

#### my.cnf
参考記事
https://qiita.com/mamy1326/items/9c5eaee3c986cff65a55

charsetや、slow query log、wait timeout、その他innodb関連設定

```
default-character-set=utf8mb4
character-set-server=utf8mb4

# slow query log
slow_query_log=true
slow_query_log-file=/var/log/mysql/mysql-slow.sql
long_query_time=1

# コネクションタイムアウト時間
wait_timeout=28800
```

#### Dockerfile
```
FROM mariadb
COPY my.cnf /etc/mysql/conf.d/my.cnf
```

### 4) redis構成
公式 dockerhub
https://hub.docker.com/_/redis

#### 構成

```
docker-lamp/
|-- redis
|   |-- Dockerfile
|   |-- data            # for redis data
|   |-- logs            # for redis log
|   `-- redis.conf      # Copy to /usr/local/etc/redis/redis.conf
```

#### redis.conf
redis-serverの設定

参考記事
https://qiita.com/uryyyyyyy/items/9ccadcccf7f7060d544a

redisのログを残すように設定

```
logfile "/var/log/redis/redis-server.log"
```

#### Dockerfile
```docker
FROM redis
RUN mkdir /var/log/redis
COPY ./redis.conf /usr/local/etc/redis/redis.conf
CMD [ "redis-server", "/usr/local/etc/redis/redis.conf" ]
```

### 5) nodeの構成
公式 dockerhub
https://hub.docker.com/_/node

#### 構成
```
|-- node
|   `-- Dockerfile
```

#### Dockerfile
```docker
FROM node:latest
RUN npm install -g gulp@3.9.1 gulp-phpunit config && \
	npm install gulp@3.9.1 gulp-phpunit config && \
	apt-get -y update && \
	apt-get -y upgrade && \
	apt-get -y install ca-certificates apt-transport-https && \
	wget -q https://packages.sury.org/php/apt.gpg -O- | apt-key add - && \
	echo "deb https://packages.sury.org/php/ stretch main" | tee /etc/apt/sources.list.d/php.list && \
	apt-get -y update && \
	apt-get -y install php7.2 php7.2-cli php7.2-common php7.2-opcache php7.2-curl php7.2-mbstring php7.2-mysql php7.2-zip php7.2-xml

WORKDIR /var/www/html
```

## 2. document root構成

```
docker-lamp/
|-- code                          # -- Mounted on /var/www/html
|   |-- config
|   |   `-- default.json.example
|   |-- gulpfile.js
|   |-- home_root                 # -- root home
|   |   `-- public                #    documentroot of lamplocal.jp
|   |       `-- index.html        #    can run only static contents.
|   |-- home_sub                  # -- virtual host home
|   |   `-- test                  #    you can add directory & use by subdomain
|   |       `-- public            #    documentroot of test.lamplocal.jp
|   |           `-- index.php     #    can run php script
|   `-- nodeapp
```

## 3. docker-compose.yml構成

```docker
version: '3.7'
services:
# centos7 apache2.4.*(http2)
  web:
    build: ./web
    container_name: lamp-web
    ports:
      - '443:443'
    volumes:
      - ./code:/var/www/html
      - ./web/logs:/var/log/httpd
      - cert:/etc/ssl/private
    restart: always
    env_file: .env
# php-fpm 7.4
  php:
    build: ./php
    container_name: lamp-php
    ports:
      - '9000'
    volumes:
      - ./code:/var/www/html
      - ./php/logs:/var/log/xdebug
    restart: always
    env_file: .env
# mariaDB
  db:
    build: ./db
    container_name: lamp-db
    restart: always
    env_file: .env
    ports:
      - 3306:3306
    volumes:
      - ./db/logs:/var/log/mysql
      - datastore:/var/lib/mysql
# phpMyadmin
  phpmyadmin:
    container_name: lamp-phpmyadmin
    image: phpmyadmin/phpmyadmin
    env_file: .env
    ports:
      - 8080:80
    depends_on:
      - db
# node js (include gulp)
  node:
    build: ./node
    container_name: lamp-node
    restart: always
    tty: true
    environment:
      - NODE_ENV=production
    ports:
      - '3000:3000'
    volumes:
      - ./code:/var/www/html
    depends_on:
      - web
# redis server
  redis:
    build: ./redis
    container_name: lamp-redis
    restart: always
    ports:
      - '6379:6379'
    volumes:
      - "./redis/data:/data"
      - "./redis/logs:/var/log/redis"
volumes:
  cert:
  datastore:

```

## 4. 動作確認

aliasを使っていますが、実行コマンドは`execute : `で出力しているので参考にしてください。

alias設定の内容と各命令の解説はこちらを参考できます。
https://qiita.com/genie-oh/items/266857d788a85e2da8f9

### 1) build

```bash
$ al docki
execute : docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

$ al dockcb
execute : docker-compose build

phpmyadmin uses an image, skipping
Building web
...
...
Successfully built 43bb05ec0f39
Successfully tagged docker-lamp_redis:latest

$ al docki
execute : docker images

REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
docker-lamp_redis   latest              43bb05ec0f39        About a minute ago   104MB
docker-lamp_node    latest              1cffc83ebe6f        About a minute ago   1.06GB
docker-lamp_db      latest              e112492cc9c2        4 minutes ago        407MB
docker-lamp_php     latest              5a3452fcbf58        4 minutes ago        671MB
docker-lamp_web     latest              9af33e8e4219        9 minutes ago        540MB
...
```

### 2) run containers
```bash
$ al dockcu
execute : docker-compose up -d

...
Status: Downloaded newer image for phpmyadmin/phpmyadmin:latest
Creating lamp-web   ... done
Creating lamp-php   ... done
Creating lamp-redis ... done
Creating lamp-db    ... done
Creating lamp-node       ... done
Creating lamp-phpmyadmin ... done

$ al dockps
execute : docker ps -a

CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS              PORTS                     NAMES
ea93226c6b49        phpmyadmin/phpmyadmin   "/docker-entrypoint.…"   17 seconds ago      Up 14 seconds       0.0.0.0:8080->80/tcp      lamp-phpmyadmin
52a68fde7bdd        docker-lamp_node        "docker-entrypoint.s…"   17 seconds ago      Up 14 seconds       0.0.0.0:3000->3000/tcp    lamp-node
13e52a01700e        docker-lamp_php         "docker-php-entrypoi…"   19 seconds ago      Up 16 seconds       0.0.0.0:32837->9000/tcp   lamp-php
43eb81b6410e        docker-lamp_web         "/usr/sbin/httpd -DF…"   19 seconds ago      Up 15 seconds       0.0.0.0:443->443/tcp      lamp-web
473ffaf3439b        docker-lamp_redis       "docker-entrypoint.s…"   19 seconds ago      Up 15 seconds       0.0.0.0:6379->6379/tcp    lamp-redis
ae80a8fd00c6        docker-lamp_db          "docker-entrypoint.s…"   19 seconds ago      Up 15 seconds       0.0.0.0:3306->3306/tcp    lamp-db
```

### 3) access web

```bash
$ curl -k https://lamplocal.me --silent | grep "<title>"
        <title>Hello World</title>

$ curl -k https://test.lamplocal.me --silent | grep "<title>"
<title>PHP 7.4.7 - phpinfo()</title><meta name="ROBOTS" content="NOINDEX,NOFOLLOW,NOARCHIVE" /></head>
```

### 4) check each package version in container 
```bash
$ al dockeit lamp-web httpd -v
execute : docker exec -it lamp-web httpd -v

Server version: Apache/2.4.41 (IUS)
Server built:   Aug 25 2019 19:41:04
```

```bash
$ al dockeit lamp-php php -v
execute : docker exec -it lamp-php php -v

PHP 7.4.7 (cli) (built: Jun 11 2020 18:41:17) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Xdebug v2.8.1, Copyright (c) 2002-2019, by Derick Rethans
```

```bash
$ al dockeit lamp-db mysql --version
execute : docker exec -it lamp-db mysql --version

mysql  Ver 15.1 Distrib 10.5.4-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2
```

```bash
$ al dockeit lamp-redis redis-server -v
execute : docker exec -it lamp-redis redis-server -v

Redis server v=6.0.5 sha=00000000:0 malloc=jemalloc-5.1.0 bits=64 build=db63ea56716d515f
```

```bash
$ al dockeit lamp-node node -v
execute : docker exec -it lamp-node node -v

v14.5.0
```

### 5) down containers

```bash
$ al dockcd
execute : docker-compose down

Stopping lamp-phpmyadmin ... done
Stopping lamp-node       ... done
Stopping lamp-php        ... done
Stopping lamp-web        ... done
Stopping lamp-redis      ... done
Stopping lamp-db         ... done
Removing lamp-phpmyadmin ... done
Removing lamp-node       ... done
Removing lamp-php        ... done
Removing lamp-web        ... done
Removing lamp-redis      ... done
Removing lamp-db         ... done
Removing network docker-lamp_default
```

### 6) 特定コンテナーのみ実行

```bash
$ dockcu php db
Creating network "docker-lamp_default" with the default driver
Creating lamp-php ... done
Creating lamp-db  ... done
```

### 7) php, mariadb, redis 連携確認
laravelをインストールし、各コネクションを確認

```php
# docker-lamp\code\home_sub\cgi\.env
DB_CONNECTION=mysql
DB_HOST=lamp-db
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=rootpw

REDIS_HOST=lamp-redis
REDIS_PASSWORD=null
REDIS_PORT=6379
```

```php
# docker-lamp\code\home_sub\cgi\app\Http\Controllers\TestController.php
<?php
namespace App\Http\Controllers;

use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\DB;

class TestController extends Controller
{
    public function index () 
    {
        $redisResult = Redis::connection()->ping('redis pong');
        $dbResult = DB::table('test')->get();

        return view('test/index', compact('redisResult', 'dbResult'));
    }
}
```

```bash
$ curl -k https://cgi.lamplocal.me/test
redisResult : redis pong
dbResult : [{"id":0,"name":"abc"}]
```

## 後書き

- 違うプラットフォームの開発完了などをDockerでコード化しておくと、いろんな開発環境に柔軟に対処できるのはいい。
- PythonやJava、Full Stack Javascript環境も構成してコード化しておきたい。
- 機会があれば、Dockerイメージのサービスデプロイ＆運用も勉強したい。（Kubernate, AWS ECS）