LoginSignup
5
12

More than 3 years have passed since last update.

VSCodeのdevcontainerでLaravel・Docker環境を構築する

Posted at

概要

VSCodeのdevcontainerを使ってLaravel環境構築を解説する記事です。
使用ツールさえ用意すれば高速で環境構築でき、Dockerを使用しているのでチームでの統一された開発環境としても使用できます。
とりあえず動かしたい人はリポジトリリンクからどうぞ。

リポジトリ

https://github.com/naoyayamamoto/laravel-docker-sample
テンプレートリポジトリとして用意しているので、雛形としても使用できます。

使用ツール

以上のツールを使用します。
DockerVisual Studio Codeについてはインストールの詳細を省きます。
Visual Studio Code Remote - ContainersについてはMicrosoft謹製のVSCodeプラグインです。リンクよりVSCodeにインストールできます。

使用方法

リポジトリをVSCodeで開く

$ git clone https://github.com/naoyayamamoto/laravel-docker-sample
$ code laravel-docker-sample
# codeコマンドが入っていなければVSCodeでリポジトリを開いてください

devcontanerを使用してVSCodeを開く

  1. VSCodeにVisual Studio Code Remote - Containersが入っていれば左下にアイコンが追加されているので、それを押してダイアログを開くか、Show All Commandscmd + shift + Pでダイアログを開く。
  2. Remote-Containers: Reopen in Containerを実行すると環境の準備が始まります。
  3. 初回はDockerの準備を行うため時間がかかりますが、2回目以降は高速で立ち上がります。

アクセス確認

http://localhost:8000へアクセスでLaravel初期ページが表示されるはずです。

laravel-8-top.jpg

解説

devcontainerを開いた際に.devcontainer/docker-compose.ymlを元にDocker環境が構築されます。
以下のコンテナを使用しており、それぞれ解説していきます。

  • nginx:alpine (web)
  • mysql:8 (db)
  • VSCode用にカスタマイズしたphp:7-fpm (app)

nginx:alpine (web)

  • デフォルトイメージを使用
  • フロントとして常に起動するので、php artisan serveなしでアクセス可能
  • .devcontainer/docker/nginx/default.confを読み込ませ、php-fpmへ処理を流している

mysql:8 (db)

  • デフォルトイメージを使用
  • .devcontainer/docker/mysql/my.cnfを読み込ませている(日本語基本設定)
  • 環境変数MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' MYSQL_DATABASE: laravelを設定しているので、rootパスワードなし、初期テーブルlaravelが作成される

VSCode用にカスタマイズしたphp:7-fpm (app)

  • devcontainerを開いた際の初期接続コンテナ
  • .devcontainer/docker/php/Dockerfileを使用してビルド
  • composernodenpmyarnが使用可能
  • php-fpmをsockで実行するために.devcontainer/docker/php/php-fpm.d/zzz-www.confを読み込ませている
  • DB_HOST: dbを設定しているので、.envでの設定よりこちらが優先されてdbコンテナに接続されます

おまけ

本番環境用のDockerfile

本番を想定してビルドを行うDockerfileがリポジトリに追加しているので、カスタマイズの元として使用してください。
マルチステージビルドを使用して、jsのコンパイルとcomposerのインストールを先行して行い、最終イメージを極力小さくしています。
GithubActionsでビルドテストだけは通しています。

kubernetesで使用する場合

参考までにkubernetesで使用する場合の設定です。
nginxとphpを1PODとして動かすことを想定しています。

参考deployment.yml
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-conf
data:
  default.conf: |
    access_log /dev/stdout main;
    error_log /dev/stderr warn;
    server {
        server_tokens off;
        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        gzip on;
        gzip_http_version 1.0;
        gzip_disable "msie6";
        gzip_proxied any;
        gzip_min_length 1024;
        gzip_comp_level 6;
        gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript;
        open_file_cache max=100000 inactive=20s;
        open_file_cache_valid 30s;
        open_file_cache_min_uses 2;
        open_file_cache_errors on;

        listen 80;
        root /workspace/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;
        }
    }
---
kind: Service
apiVersion: v1
metadata:
  name: laravel-service
spec:
  selector:
    app: laravel
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      name: laravel-http
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: laravel
  labels:
    app: laravel
spec:
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: laravel
  template:
    metadata:
      labels:
        app: laravel
    spec:
      containers:
        - name: app
          image: myimage
          volumeMounts:
            - mountPath: /var/run/php-fpm
              name: php-fpm-socket
            - mountPath: /shared
              name: public-contents
          lifecycle:
            postStart:
              exec:
                command: ["/bin/sh", "-c", "cp -aT /workspace/public /shared"]
        - name: web
          image: nginx:alpine
          ports:
            - containerPort: 80
          volumeMounts:
            - mountPath: /var/run/php-fpm
              name: php-fpm-socket
            - mountPath: /etc/nginx/conf.d
              name: nginx-conf
            - mountPath: /workspace/public
              name: public-contents
      volumes:
        - name: php-fpm-socket
          emptyDir: {}
        - name: public-contents
          emptyDir: {}
        - name: nginx-conf
          configMap:
            name: nginx-conf
            items:
              - key: default.conf
                path: default.conf

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