Deploy Laravel App ด้วย Docker และ MySQL ครบทุกขั้นตอน

ทำไมต้อง Deploy Laravel ด้วย Docker?

การ Deploy Laravel ผ่าน Docker ช่วยให้ทีมทุกคนใช้ Environment เดียวกัน ย้าย Server ได้ง่าย และไม่มีปัญหา “works on my machine” อีกต่อไป

โครงสร้าง Project

laravel-docker/
├── app/              # Laravel source code
├── docker/
│   ├── nginx/
│   │   └── default.conf
│   └── php/
│       └── Dockerfile
├── .env.docker
└── docker-compose.yml

Dockerfile สำหรับ Laravel (PHP 8.2)

FROM php:8.2-fpm-alpine

# ติดตั้ง Dependencies
RUN apk add --no-cache \
    libpng-dev \
    libjpeg-turbo-dev \
    libwebp-dev \
    zip \
    libzip-dev \
    unzip \
    nodejs \
    npm

# ติดตั้ง PHP Extensions
RUN docker-php-ext-install \
    pdo \
    pdo_mysql \
    zip \
    gd \
    bcmath \
    opcache

# ติดตั้ง Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

WORKDIR /var/www/html

# คัดลอก Composer dependencies
COPY composer.json composer.lock ./
RUN composer install --no-dev --no-scripts --no-autoloader

# Copy source code
COPY . .
RUN composer dump-autoload --optimize

# Permissions
RUN chown -R www-data:www-data storage bootstrap/cache

EXPOSE 9000
CMD ["php-fpm"]

Nginx config (docker/nginx/default.conf)

server {
    listen 80;
    root /var/www/html/public;
    index index.php;

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

    location ~ \.php$ {
        fastcgi_pass app:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}

docker-compose.yml

version: '3.8'
services:
  app:
    build:
      context: .
      dockerfile: docker/php/Dockerfile
    container_name: laravel_app
    restart: unless-stopped
    volumes:
      - .:/var/www/html
      - /var/www/html/vendor
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_healthy
    environment:
      APP_ENV: production
      APP_KEY: ${APP_KEY}
      DB_HOST: mysql
      DB_DATABASE: ${DB_DATABASE}
      DB_USERNAME: ${DB_USERNAME}
      DB_PASSWORD: ${DB_PASSWORD}
      REDIS_HOST: redis
      CACHE_DRIVER: redis
      SESSION_DRIVER: redis

  nginx:
    image: nginx:1.25-alpine
    container_name: laravel_nginx
    restart: unless-stopped
    ports:
      - "80:80"
    volumes:
      - .:/var/www/html
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - app

  mysql:
    image: mysql:8.0
    container_name: laravel_mysql
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
      MYSQL_DATABASE: ${DB_DATABASE}
      MYSQL_USER: ${DB_USERNAME}
      MYSQL_PASSWORD: ${DB_PASSWORD}
    volumes:
      - mysql_data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

  redis:
    image: redis:7-alpine
    container_name: laravel_redis
    restart: unless-stopped
    volumes:
      - redis_data:/data
    command: redis-server --appendonly yes
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 3

volumes:
  mysql_data:
  redis_data:

ไฟล์ .env.docker

APP_NAME=MyLaravel
APP_ENV=production
APP_KEY=base64:your-app-key-here
APP_DEBUG=false
APP_URL=https://yourdomain.com

DB_ROOT_PASSWORD=rootpassword
DB_DATABASE=laravel_db
DB_USERNAME=laravel_user
DB_PASSWORD=securepassword

Deploy ครั้งแรก

# Copy .env
cp .env.docker .env

# Build และ Start
docker compose up -d --build

# Generate App Key
docker exec laravel_app php artisan key:generate

# Run Migrations
docker exec laravel_app php artisan migrate --force

# Clear Cache
docker exec laravel_app php artisan config:cache
docker exec laravel_app php artisan route:cache
docker exec laravel_app php artisan view:cache

Queue Worker

  queue:
    build:
      context: .
      dockerfile: docker/php/Dockerfile
    command: php artisan queue:work --sleep=3 --tries=3 --max-time=3600
    restart: unless-stopped
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_healthy

สรุป

การ Deploy Laravel ด้วย Docker ให้ความยืดหยุ่นและเสถียรภาพสูง สามารถ Scale เพิ่ม Worker ได้ง่ายโดยไม่ต้องแก้ไข Server เลย