Docker

既存LaravelプロジェクトをDocker(Alpine Linux)で動かす

Laravel-docker
o_wani
この記事は作成から3年以上経過しているため、内容が古くなっている可能性があります。

ローカル環境がVagrantで動いているLaravelの既存プロジェクトがある。

今回はその既存プロジェクトをローカルの開発環境Dockerでも動くようにした。ネット上ではいろいろな、docker-compose.ymlがあるが、今回は自分のローカルで動作する内容を記載しておく。

また既存プロジェクトでは、ファイルを扱うライブラリ「libreoffice」やメール受信のための「imap」も使用しているためそれに対応した。

既存プロジェクト環境
  • composer 1.8.0
  • PHP 7.2.34 / Laravel 5.7
  • Mysql 5.7.24
  • nginx 1.12.2

各ミドルウェアのバージョンは保ち動作させるように配慮した。
(ローカル環境と本番環境は動作の整合性を保つために合わせる)

※今回はPHP7.2のDocker Imageがないっぽいので、PHP7.4を使用する。

前準備

ローカルで環境構築のための各ツール「git」「docker」「docker-compose」をインストールしておく。

  • git
$ git --version
git version 2.17.1.windows.2
  • docker
$ docker --version
Docker version 19.03.1, build 74b1e89e8a
  • docker-compose
$ docker-compose --version
docker-compose version 1.24.1, build 4667896b

プロジェクトのディレクトリ構造

今回のディレクトリ構造は下記のとおり。「アプリ」「DB」「WEB」の3つのイメージを動かす。

.
├── www  [アプリ]
├── Dockerfile  [本番環境デプロイ用]
├── Vagrantfile
├── docker-compose.yml [開発環境デプロイ用]
├── infra [開発環境デプロイ用]
      └── docker
            ├── mysql
            ├── nginx
            └── php

各種設定ファイル

  • docker-compose.yml
version: "3.8"
volumes:
  php-fpm-socket:
  db-store:
services:
  db:
    image: mysql:5.7
    container_name: db
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_PASSWORD:-secret}
      MYSQL_DATABASE: ${DB_DATABASE:-db}
      MYSQL_USER: ${DB_USERNAME:-db_user}
      MYSQL_PASSWORD: ${DB_PASS:-password}
      TZ: 'Asia/Tokyo'
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    volumes:
    - ./infra/docker/mysql/db-store:/var/lib/mysql
    - ./infra/docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf
    - ./infra/docker/mysql/sql:/docker-entrypoint-initdb.d
    ports:
    - 3306:3306
  web:
    build:
      context: .
      dockerfile: ./infra/docker/nginx/Dockerfile
    ports:
      - ${WEB_PORT:-80}:80
    volumes:
      - php-fpm-socket:/var/run/php-fpm
      - ./www:/work/www
  app:
    build:
      context: .
      dockerfile: ./infra/docker/php/Dockerfile
    volumes:
      - php-fpm-socket:/var/run/php-fpm
      - ./www:/work/www
    environment:
       DB_CONNECTION: mysql
       DB_HOST: db
       DB_PORT: 3306
       DB_DATABASE: ${DB_DATABASE:-db}
       DB_USERNAME: ${DB_USERNAME:-db_user}
       DB_PASSWORD: ${DB_PASSWORD:-password}
    links:
      - db

  • データベース
    ./infra/docker/mysql/my.cnf
[mysqld]
character_set_server = utf8mb4

# timezone
default-time-zone = SYSTEM
log_timestamps = SYSTEM

# Error Log
log-error = mysql-error.log

# Slow Query Log
slow_query_log = 1
slow_query_log_file = mysql-slow.log
long_query_time = 1.0
log_queries_not_using_indexes = 0

# General Log
general_log = 1
general_log_file = mysql-general.log

[mysql]
default-character-set = utf8mb4

[client]
default-character-set = utf8mb4
  • Webサーバ
    ./infra/docker/nginx/Dockerfile
FROM node:14.2-alpine as node
FROM nginx:1.12-alpine
SHELL ["/bin/ash", "-oeux", "pipefail", "-c"]

ENV TZ=Asia/Tokyo

RUN apk update && \
  apk add --update --no-cache --virtual=.build-dependencies g++

# node command
COPY --from=node /usr/local/bin /usr/local/bin
# npm command
COPY --from=node /usr/local/lib /usr/local/lib
# yarn command
COPY --from=node /opt /opt
# nginx config file
COPY ./infra/docker/nginx/default.conf /etc/nginx/conf.d/default.conf

WORKDIR /work/www
./infra/docker/nginx/default.conf
nginxの設定ファイルは以下。
access_log /dev/stdout main;
error_log /dev/stderr warn;

server {
    listen 80;
    root /work/www/public;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options "nosniff";

    index index.html index.htm index.php;

    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    error_page 404 /index.php;

    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}
  • アプリ
    ./infra/docker/php/Dockerfile
FROM php:7.4-fpm-alpine

COPY ./.env.example ./www/.env
COPY ./www /work/www
COPY ./infra/docker/php/php-fpm.d/www.conf /usr/local/etc/php-fpm.d/www.conf
COPY ./infra/docker/php/php.ini /usr/local/etc/php/php.ini

# timezone environment
ENV TZ=Asia/Tokyo
# locale
ENV LANG=ja_JP.UTF-8
# JSTに変更
RUN apk add tzdata && \
    cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

RUN apk upgrade --update && \
  apk --no-cache add icu-dev autoconf make g++ gcc ca-certificates wget curl

# for gd
RUN apk add --no-cache \
        freetype-dev \
        libjpeg-turbo-dev \
        libpng-dev

# for imap
RUN apk add imap-dev krb5-dev libressl-dev

# 使用するモジュール追加
RUN apk add --no-cache php7-bcmath php7-pecl-memcached unzip libzip-dev
RUN docker-php-ext-install gd intl pdo_mysql opcache zip bcmath

# for imap
RUN PHP_OPENSSL=yes \
    docker-php-ext-configure imap --with-kerberos --with-imap-ssl \
    && docker-php-ext-install imap \
    && docker-php-ext-enable imap

# for libreoffice
RUN mkdir -p /usr/share/man/man1
RUN apk add --no-cache libreoffice

# for composer
ENV COMPOSER_VERSION 1.8.0

RUN curl -L -O https://getcomposer.org/download/${COMPOSER_VERSION}/composer.phar && \
    chmod +x composer.phar && mv composer.phar /usr/local/bin/composer

WORKDIR /work/www
./infra/docker/php/php.ini
phpの設定ファイルは以下。
zend.exception_ignore_args = off
expose_php = on
max_execution_time = 30
max_input_vars = 1000
upload_max_filesize = 64M
post_max_size = 128M
memory_limit = 256M
error_reporting = E_ALL
display_errors = on
display_startup_errors = on
log_errors = on
error_log = /dev/stderr
default_charset = UTF-8

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

[mysqlnd]
mysqlnd.collect_memory_statistics = on

[Assertion]
zend.assertions = 1

[mbstring]
mbstring.language = Japanese
mbstring.internal_encoding = "UTF-8"
./infra/docker/php/php-fpm.d/www.conf
[www]
listen = /var/run/php-fpm/php-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0666

ビルド

$ docker-compose up --build
....
....
$ docker-compose ps
Name     Command                       State      Ports
----------------------------------------------------------
app_1   docker-php-entrypoint php-fpm    Up      9000/tcp
web_1   nginx -g daemon off;             Up      0.0.0.0:80->80/tcp
db         docker-entrypoint.sh mysql ... Up      0.0.0.0:3306->3306/tcp, 33060/tcp

http://localhostでアクセスできるはずです。
できなければ docker-machine envなどでIPアドレスを確認してそこにアクセスするといいかもしれません。

また、何回か試している過程で下記エラーがあった場合

Illuminate\Database\QueryException : SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo failed: Name does not resolve

いったんイメージを削除してビルドするとなおりました。

$ docker-compose down --rmi all --volumes
STAFF
o_wani
o_wani
スタッフ
大学卒業後、15年間WEB業界で働く。現在はマネジメントに従事していますが、ChatGPTの登場に触発され、このブログを再開。AIをパートナーに、自分で手を動かして実装する楽しさと喜びを再発見中。時代が変わりつつある中でも、陳腐化しない情報発信も目指しています。
記事URLをコピーしました