5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

自己学習を兼ねて在宅・出社把握アプリを作成 その2・Docker環境の構築とLaravelのインストール

Last updated at Posted at 2024-12-25

こんにちは、無資格・無免許エンジニアの三木です。

前回こちらで
何もわからない状態から開発を始めて
「できあがりはこちらです」と3分クッキングのような記事を書かせて頂いたのですが
ここから順番に、どのように環境を用意していったかを記事にしたいと思います

本記事はdocker-composeの設定+Laravelのインストールののち、localhost接続でLaravelのページが表示されるまでを書かせて頂きます。

開発マシンの前提

WindowsでもMacでも良いのですが
Windowsの場合はWSL2+Ubuntuが起動する状態になっていて

Windows → ターミナルソフトなどでUbuntu上から、ルートディレクトリ以下の操作が出来る
Mac → ターミナルからルートディレクトリ以下の操作が出来る

という状態を前提として考えています。

Docker DesktopによるDockerコンテナの立ち上げ

Webのシステムを開発するにはweb(http)やdatabaseなどの複数のサーバーが必要になります

これらを物理的に1台づつ用意して…ということをやっているケースはもうあまりなく
DockerやVirtualBoxなどの仮想環境でPC上に構築することが多いです

必要なサーバーごとにDocker環境を一つづつ立ち上げるということも可能ですが
複数あったときにまとめて起動・停止が出来れば便利です

これを可能にするDocker-ComposeをWindows/Macのアプリケーションとして利用できるのがDocker Desktopとなります。

ポータルはDocker Desktopを利用してローカルホスト内に下記を作成し、そこで開発をおこなっています

  • ネットワークブリッジ
  • Webコンテナ
  • DBコンテナ
  • Redisコンテナ

docker.png

まずはこのDockerコンテナの環境を作成していくのですが
Ubuntu/Macのターミナルで作業したい空のディレクトリに入り
下記のコマンドで何かしらバージョンが表示される状態になっていれば作成を開始できます

$ docker-compose -v
Docker Compose version v2.31.0-desktop.2

Windowsの場合はSetting->Resources->WSL integrationあたりの項目にある

  • Enable integration with my default WSL distro
  • [Ubuntu]などの対象OSのトグル

image.png

の項目のチェックが必要です

ここからコンテナ設定を作成し、起動させていきます。

設定ファイルの配置と作成

ファイルは下記のように配置しました

└── root/
    ├── docker/
    │   ├── db/
    │   │   └── my.cnf
    │   └── web/
    │       ├── apache-virtualhost.conf
    │       ├── Dockerfile
    │       └── server.sh
    ├── portal-app/
    │   └── ※ここは空
    └── docker-compose.yml

一旦1ファイルづつ説明していきます。
各ファイル・設定は表題のアプリを開発するにあたってこのように用意した…
という一例なので、利用したいコンテナなどによって全然違う構成になると思います。

docker-compose.yml

Docker-Composeの設定ファイルです。
ここに記載している内容を元にコンテナをビルド・起動・停止します。
下記のファイルではweb/db/redisのサーバーをローカルのネットワークブリッジに立ち上げるための設定です。

docker-compose.yml
###########################
# ローカル開発環境

services:
  ###########################
  # portal_web / webサーバー
  # このブロック1つがサーバー(コンテナ)1つを表す
  portal_web:
    container_name: portal_web    # コンテナ名、ブリッジ内で名前引きするので大事
    build: docker/web             # ビルド時にDockerfileを参照する場合に指定
    environment:
      - APP_TIMEOUT=60
      - PHP_MEMORY_LIMIT=256M
      - PHP_MAX_UPLOAD=20M
    working_dir: /var/www/html/portal-app   # コンテナにログインした際の初期ディレクトリ
    ports:
      - "9190:80"   # localhost:9190への接続をこのサーバーの80ポートにフォワーディング
      - "5173:5173" # localhost:5173への接続をこのサーバーの5173ポートにフォワーディング
    networks:
      - portal_local   # 使用するネットワークブリッジ、設定は末尾
    volumes:
      - ./:/var/www/html   # このディレクトリをコンテナ内/var/www/html以下にマッピングする

  ###########################
  # portal_db : mysql 8.4.3
  # DBサーバー
  portal_db:
    container_name: portal_db
    image: mysql:8.4.3    # webと異なり、imageから直接作成
    #ports:
    #  - 3306:3306        # もしブリッジ外からDBへ接続したいなら設定が必要
    environment:          # 立ち上がるDBのDB名やuser名、ローカルは適当で大丈夫
      MYSQL_DATABASE: portal
      MYSQL_USER: portal
      MYSQL_PASSWORD: portal
      MYSQL_ROOT_PASSWORD: portal
      TZ: 'Asia/Tokyo'
    networks:
      - portal_local    # 使用するネットワークブリッジ、設定は末尾
    volumes:               
      - portal_db_volume:/var/lib/mysql      # 永続化のため名前付きボリュームを利用、設定は末尾
      - ./docker/db/conf.d:/etc/mysql/conf.d # 起動時の文字コード設定変更のため、参照confを変更

  ###########################
  # portal__redis : Redis 7.4.1
  # Redisサーバー
  portal_redis:
    container_name: portal_redis
    image: redis:7.4.1    # webと異なり、imageから直接作成
    #ports:
    #  - "6379:6379"      # もしブリッジ外からRedisへ接続したいなら設定が必要
    volumes:
      - portal_redis_volume:/data            # 永続化のため名前付きボリュームを利用、設定は末尾
    networks:
      - portal_local      # 使用するネットワークブリッジ、設定は末尾

networks: # コンテナを立ち上げるネットワークブリッジの設定
  portal_local:
    name: portal_local
    driver: bridge
    driver_opts:
      com.docker.network.enable_ipv6: "false"
    ipam:
      driver: default
      config:
        - subnet: 192.168.200.0/24  # 一応クラスCのプライベート範囲を設定しています

volumes: # DBやRedisのデータ永続化のために利用する名前つきボリューム
  portal_db_volume:
    driver: local
  portal_redis_volume:
    driver: local

Dockerfile(docker/web/Dockerfile)

Webサーバー(portal_web)のビルド時に利用されるコンテナの設定ファイルです。
コンテナのビルド時にのみ、上から順にRUNやCOPYで指定したコマンドが実行されていきます。

# DBやRedisと同様に元となるコンテナイメージを指定
FROM php:8.4.2-apache-bookworm

# 使う予定のPHP拡張などをインストール
RUN apt-get update \
 && apt-get install -y libzip-dev unzip \
 && docker-php-ext-install zip pdo mysqli pdo_mysql \
 && docker-php-ext-install opcache \
 && yes '' | pecl install redis

# Laravel他のインストールなどを管理するcomposerをインストール
RUN curl https://getcomposer.org/download/2.8.4/composer.phar -o /usr/local/bin/composer -s \
 && chmod 755 /usr/local/bin/composer

# npmコマンドやnode.jsを利用するためnodeをインストール
RUN curl -sL https://deb.nodesource.com/setup_22.x | bash -\
 && apt-get install -y nodejs

# コンテナ上でgitコマンドを利用したいためgitをインストール
RUN apt-get update && \
    apt-get install -y git
RUN git config --global --add safe.directory /var/www/html

# apacheの設定ファイルを上書きする
COPY apache-virtualhost.conf /etc/apache2/sites-enabled/000-default.conf
# apache起動のためのシェルをコピーし、実行できる権限にする
COPY server.sh /usr/local/bin/server.sh
RUN chmod 755 /usr/local/bin/server.sh

# 起動後にシェルを実行する
ENTRYPOINT ["/usr/local/bin/server.sh"]

server.sh(docker/web/server.sh)

Dockerfileの末尾で指定した起動後に実施するシェル
apacheの実行ユーザーを追加して、apacheを起動
(このため、コンテナが起動した後に、apacheでhttpの接続を待ち受ける状態になる)

server.sh
#!/bin/sh

# get current user setting.
USER=`grep apache /etc/passwd`

# set user if user is not exist.
if [ -z "$USER" ] && [ ! -z "$APACHE_UID" ]; then
  useradd -u $APACHE_UID  apache
  mkdir -m 755 /home/apache
  chown apache /home/apache
  export APACHE_RUN_USER=apache
fi

# start apache.
apache2-foreground

wait

apache-virtualhost.conf(docker/web/apache-virtualhost.conf)

Dockerfileの最後の方で上書きしているapacheの設定ファイル
この後Laravelをインストールした後に、80番ポートへの接続を/var/www/html/portal-app/public
へマッピングしたいために用意

apache-virtualhost.conf
<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html/portal-app/public
    DirectoryIndex index.php
    <Directory /var/www/html/portal-app>
        Options FollowSymLinks
        Options -Indexes
        AllowOverride All

        # set allow IP address.
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

my.cnf(docker/db/conf.d/my.cnf)

docker-compose.ymlの設定でビルド時にコピーを実施
そのままDBを起動してしまうと文字コード設定が一部latin1などになってしまうので設定

my.cnf
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci

[client]
default-character-set=utf8mb4

ポートマッピングについて

以上の設定ファイルでWeb/DB/Redisのサーバーを立ち上げることができます。
ただしそれだけでは、全てのコンテナが一つのネットワークブリッジ上に立ち上がるため
サーバー間の通信は可能ですが、ブリッジの外からWebサーバーへアクセスすることができず、開発中の画面を確認することができません。

このためdocker-compose.ymlのファイルに

ports:
      - "9190:80"   # localhost:9190への接続をこのサーバーの80ポートにフォワーディング
      - "5173:5173" # localhost:5173への接続をこのサーバーの5173ポートにフォワーディング

の設定を追加して、開発中の環境にアクセスできるようにしています。

portmapping.png

コンテナの起動と確認

コンテナのビルド方法

docker-compose.ymlのあるディレクトリで

$ docker compose build

でコンテナのイメージが作成されます。
もし途中Dockerfileを編集した場合はimageの更新が必要なため、上記の再実行が必要です。

また、ビルドにはキャッシュが利用されるのですが
意図しないキャッシュ利用が発生している場合などは下記コマンドでキャッシュなしビルドが可能です。

$ docker compose build --no-cache

コンテナの起動方法

作成したコンテナイメージの起動は下記のコマンドで出来ます

$ docker compose up -d

また、立ち上がっているコンテナは下記のコマンドで確認可能です

$ docker-compose ps
NAME           IMAGE             COMMAND                  SERVICE        CREATED          STATUS          PORTS
portal_db      mysql:8.4.3       "docker-entrypoint.s…"   portal_db      45 minutes ago   Up 45 minutes   3306/tcp, 33060/tcp
portal_redis   redis:7.4.1       "docker-entrypoint.s…"   portal_redis   45 minutes ago   Up 45 minutes   6379/tcp
portal_web     no02-portal_web   "/usr/local/bin/serv…"   portal_web     45 minutes ago   Up 45 minutes   0.0.0.0:5173->5173/tcp, 0.0.0.0:9190->80/tcp

もしSTATUS = UPとなっていない場合はどこかで失敗しています
-dオプションを外すことで
各コンテナのログ出力から問題を特定することが出来るかもしれません

$ docker-compose up
[+] Running 4/4
 ✔ Network portal_local    Created                                                                                                                          0.1s 
 ✔ Container portal_web    Created                                                                                                                          0.1s 
 ✔ Container portal_db     Created                                                                                                                          0.1s 
 ✔ Container portal_redis  Created                                                                                                                          0.1s 
Attaching to portal_db, portal_redis, portal_web
portal_redis  | 1:C 24 Dec 2024 07:53:02.717 * oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
portal_redis  | 1:C 24 Dec 2024 07:53:02.717 * Redis version=7.4.1, bits=64, commit=00000000, modified=0, pid=1, just started
…

webサーバーコンテナへのシェルログイン

作成したWebコンテナへのログインは以下のコマンドで出来ます
ログイン先はdocker-compose.ymlで指定したcontainer_nameの値を指定します

$ docker exec -it portal_web bash
root@5121f2f7b75d:/var/www/html/portal-app# (以降の入力はwebコンテナのbashに)

コンテナから抜けるときは下記となります

root@5121f2f7b75d:/var/www/html/portal-app# exit
$ (元のターミナルに戻ってくる)

dbサーバーのシェルログイン

作成したDBコンテナのログインは以下のコマンドで出来ます
DBはenvironmentの設定によりビルド完了時にデータベースの作成まで完了しています。

試しにmysqlにログインし、database一覧を表示するなら下記のようになります
mysqlのユーザー名・パスワードやデータベース名などはdocker-compose.ymlで設定したenviromentの値を利用します

$ docker exec -it portal_db bash
bash-5.1# mysql -uportal -pportal  <---- 警告を嫌うなら[mysql -uportal -p]として後入力に
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 12
Server version: 8.4.3 MySQL Community Server - GPL

Copyright (c) 2000, 2024, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| performance_schema |
| portal             |  <---- environmentで指定したDBが出来上がっている
+--------------------+
3 rows in set (0.00 sec)

mysql> exit    <---- mysqlから抜ける
Bye
bash-5.1# exit   <---- DBコンテナから抜ける
exit

redisサーバーのシェルログイン

作成したReidsコンテナのログインは以下のコマンドで出来ます
redis-cliを起動し、登録されているKeyを調べるなら以下のようになります。

$ docker exec -it portal_redis bash
root@36bde9c8d794:/data# redis-cli    <--- redis-cliを起動
127.0.0.1:6379> KEYS *    <--- キー一覧を表示、立上げ直後は何もない
(empty array)

コンテナの停止方法

docker-compose.ymlのあるディレクトリで下記のコマンドで停止できます

$ docker-compose down
[+] Running 4/4
 ✔ Container portal_web    Removed
 ✔ Container portal_db     Removed
 ✔ Container portal_redis  Removed
 ✔ Network portal_local    Removed                                                
$

ここまで問題なく動作すれば

  • 開発で利用するサーバーが自分のマシン内に用意出来ている
  • 各マシンにログインして現在の状況を確認する手法が整っている

といえると思います。

Laravelのインストール

WebコンテナにログインしてComposer経由でLaravelをインストールします

$ docker exec -it portal_web bash
root@8930d5732a83:/var/www/html/portal-app# composer create-project laravel/laravel .

また、Redisへの接続にpredisを利用するためcomposerからpredisのインストールも実施

root@8930d5732a83:/var/www/html/portal-app# composer require --dev predis/predis

これでportal-appディレクトリ以下にLaravelフレームワークがインストールされます
余計なmigrationなども動作してしまいますが、一旦このままで

composer.json

どういったツール&バージョンをインストールしたいかを記述します
"laravel/framework": "^11.31"という表記であれば

  • メジャーバージョン11は固定
  • マイナーバージョン31以上で依存性の問題のない最新バージョン

という意味になります。

composer.lock

実際に何をインストールしたかを記述しています
このファイルが他者と共有されることで、他の人の環境でも同一バージョンのツールをインストールすることができます。

rootユーザーでコンテナに接続してしまっているので所有権限を変更し
本来はインストールや操作するユーザーを気を遣うところですが、ローカル環境…ということでログやキャッシュの出力先のアクセス権を緩くしておきます

root@8930d5732a83:/var/www/html/portal-app# chown -R 1000:1000 .
root@8930d5732a83:/var/www/html/portal-app# chmod 777 -R storage

portal-appディレクトリ直下に.envという環境パラメータを設定するファイルが出来上がっているはずなので
以下を参考に立ち上げたコンテナのcontainer-nameなどを設定します

※同一ブリッジ内のため、Webから見てcontainer-nameで通信が出来る状態になっています

.env
APP_NAME=portal   <-- 一応アプリ名に変更
APP_ENV=local
APP_KEY=base64:NTRRUl0n24WXDHmdyEnJ9bvEvoFToGDDlD1Ox3+C4fk=
APP_DEBUG=true
APP_TIMEZONE=Asia/Tokyo   <-- JSTに変更
APP_URL=http://localhost:9190   <-- 9190にマッピングしたので変更

APP_LOCALE=ja   <-- 言語を変更
APP_FALLBACK_LOCALE=en
APP_FAKER_LOCALE=ja_JP   <-- Fakerの言語を変更

APP_MAINTENANCE_DRIVER=file
# APP_MAINTENANCE_STORE=database

PHP_CLI_SERVER_WORKERS=4

BCRYPT_ROUNDS=12

LOG_CHANNEL=stack
LOG_STACK=single
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug

DB_CONNECTION=mysql   <-- mysqlへ変更
DB_HOST=portal_db   <-- DBコンテナへ変更
DB_PORT=3306
DB_DATABASE=portal   <-- docker-compose.ymlで設定したユーザー名などに変更
DB_USERNAME=portal   <-- 同上
DB_PASSWORD=portal   <-- 同上

SESSION_DRIVER=redis   <-- redisへ変更
SESSION_LIFETIME=120
SESSION_ENCRYPT=false
SESSION_PATH=/
SESSION_DOMAIN=null

BROADCAST_CONNECTION=log
FILESYSTEM_DISK=local
QUEUE_CONNECTION=database

CACHE_STORE=redis
CACHE_PREFIX=

MEMCACHED_HOST=127.0.0.1

REDIS_CLIENT=predis   <-- predisへ変更
REDIS_HOST=portal_redis   <-- Redisコンテナ名へ変更
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_MAILER=log
MAIL_SCHEME=null
MAIL_HOST=127.0.0.1
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="${APP_NAME}"

AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false

VITE_APP_NAME="${APP_NAME}"

記事作成時点のLaravel最新バージョンで上記作成していますが、見覚えのないパラメータも増えていました。
実行いただくタイミングによっては用意される.envは上記と異なるものになると思います。

念のためここでmigrateを実行してみて、DBへの接続が問題ないか確認します

root@8930d5732a83:/var/www/html/portal-app# php artisan migrate

   INFO  Preparing database.

  Creating migration table ...... 22.88ms DONE

   INFO  Running migrations.

  0001_01_01_000000_create_users_table ...... 87.43ms DONE
  0001_01_01_000001_create_cache_table ...... 35.44ms DONE
  0001_01_01_000002_create_jobs_table ...... 65.95ms DONE

php artisan migrateを実行した後に、DBコンテナで上記コマンドが作成したであろうテーブルが確認できれば問題ありません
今回はusersなどが相当します

$ docker exec -it portal_db bash
bash-5.1# mysql -uportal -p
(input password ...)
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> use portal;

Database changed
mysql> show tables;
+-----------------------+
| Tables_in_portal      |
+-----------------------+
| cache                 |
| cache_locks           |
| failed_jobs           |
| job_batches           |
| jobs                  |
| migrations            |
| password_reset_tokens |
| sessions              |
| users                 |
+-----------------------+
9 rows in set (0.01 sec)

接続確認

ここまで問題がなければ
PCからブラウザでhttp://localhost:9190/へアクセスすると

image.png

上記のようにLaravelのインストール直後の画面が表示されると思います。
ここからLaravel上での開発を進めていける状態となります。

次はPHP実装やReact実装…ではなくterraformの記事を作成していこうと思います。
読んでいただきありがとうございました。

5
1
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
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?