สร้าง LEMP stack ด้วย docker

อยากทำ dev environment สำหรับทำเว็บที่ไม่กระทบกับ environment ของเครื่องที่ใช้อยู่ โดยมีของที่อยากได้คือ linux, nginx, mariadb และ php (LEMP) จริง ๆ จะเป็น linux, apache, mysql และ php (LAMP) ก็ได้ แต่เอา nginx มาใช้แทนเพราะอยากหัดด้วย ส่วน mariadb เห็นว่า performance ดีกว่า mysql เลยเลือก mariadb ตั้งโจทย์ไว้แบบนี้เลยมอง ๆ เรื่องเอา docker มาใช้

เคยหัด docker มาหลายที ได้แต่หัด ไม่เคยใช้สักที ดิวกับนเรศเคยบอกไว้ว่า อย่าหัด ให้ใช้เลย ก็เลยเออ เอามาลองกับไอ้นี่แหละ

แรกสุดลองด้วยวิธีสร้าง docker ของที่อยากได้แต่ละตัว แล้วก็เจอปัญหาว่าตอนจะ start ทั้งหมดก็วุ่นวาย ตอนจะ stop ทั้งหมดก็ลำบาก (ถึงแม้ว่าจะง่ายกว่าตอนไม่ได้ใช้ docker) จนไปเจอทางเลือกที่น่าสนใจ คือ docker compose

docker-compose.yml

docker compose จะสร้าง containers จาก docker-compose.yml ที่เรากำหนดไว้แล้ว docker-compose.yml ที่เอาไว้สร้าง LEMP stack ที่ต้องการสุดท้ายได้หน้าตาออกมาแบบนี้

version: '2'

volumes:
  database_data:
    driver: local

services:
  nginx:
    image: nginx:latest
    ports:
      - 8080:80
    volumes:
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
    volumes_from:
      - php
  php:
    build: ./docker/php/
    expose:
      - 9000
    volumes:
      - ./html:/var/www/html
  mariadb:
    image: mariadb:latest
    ports:
      - 3306:3306
    volumes:
      - ./docker/mariadb:/opt/data
    command: --init-file /opt/data/migration.sql
    environment:
      - MYSQL_ROOT_PASSWORD=rootpassword
      - MYSQL_DATABASE=lempdb
      - MYSQL_USER=lemp
      - MYSQL_PASSWORD=lemppassword

ส่วนที่สำคัญจะแยกออกเป็น

nginx

  nginx:
    image: nginx:latest
    ports:
      - 8080:80
    volumes:
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
    volumes_from:
      - php

configuration นี้จะบอกว่าให้ใช้ image จาก nginx:latest และทำการ map port จาก 8080 ไปที่ 80 ดังนั้นถ้าทุกอย่าง ok เราจะสามารถเข้าใช้งานได้ผ่าน http://localhost:8080 มีการ map file ./docker/nginx/default.conf เข้าไปเป็น local file /etc/nginx/conf.d/default.conf เพื่อเอาไปใช้เป็น configuration ให้กับ nginx นอกจากนี้แล้ว ยังเพิ่ม disk ที่เป็นตัวเดียวกันกับที่ประกาศไว้ใน configuration ของ php ด้วย

php

  php:
    build: ./docker/php/
    expose:
      - 9000
    volumes:
      - ./html:/var/www/html

configuration นี้บอกว่าเวลา build image ให้ดูจากไฟล์ Dockerfile ใน ./docker/php เสร็จแล้วให้เปิด port 9000 ไว้ด้วย และให้ทำการ map disk จากเครื่องเราที่ ./html ไปเป็น local /var/www/html ในเครื่อง php ด้วย (path นี้ nginx จะเห็นด้วยเหมือนกัน เพราะใน nginx configuration มีการประกาศ volumes_from จาก php ไว้)

ตอนเวลาเรา dev โค้ดทุกอย่างเราก็เอาไปวางไว้ใน ./html ได้เลย

mariadb

  mariadb:
    image: mariadb:latest
    ports:
      - 3306:3306
    volumes:
      - ./docker/mariadb:/opt/data
    command: --init-file /opt/data/migration.sql
    environment:
      - MYSQL_ROOT_PASSWORD=rootpassword
      - MYSQL_DATABASE=lempdb
      - MYSQL_USER=lemp
      - MYSQL_PASSWORD=lemppassword

configuration นี้บอกว่า build image โดยใช้ mariadb:latest และ map port 3306 ออกมาให้ใช้ ส่วน data ให้เก็บไว้ที่ ./docker/mariadb โดยการ map volume เข้าไปไว้ที่ data path ของ mariadb นอกจากนี้แล้วมีการกำหนดค่าเริ่มต้นให้กับ database ผ่าน environment variables คือ MYSQL_ROOT_PASSWORD, MYSQL_DATABASE, MYSQL_USER, MYSQL_PASSWORD ดังนั้นหลังจากที่เราสร้าง container นี้เสร็จ database ที่ได้จะมีชื่อ รหัสผ่านของ root ชื่อของ user และรหัสผ่านของ user ตามที่เรากำหนดไว้

ปิดท้ายด้วย command: --init-file /opt/data/migration.sql เอาไว้สำหรับสร้าง database เริ่มต้นผ่าน migration script ดังนั้น ถ้าอยากสร้าง table หรือใส่ data อะไรลงไปตั้งแต่ตอนสร้าง container ก็ทำได้เลย

spin up

วิธีการสร้าง containers ทั้งหมด + start service ก็ง่ายมาก

docker-compose up -d

เลิกใช้แล้วอยากจะลบ container, network, volume ทั้งหมดก็แค่

docker-compose down

หรืออยากจะแค่ stop service ไว้ภายหลังจะได้มาใช้ต่อ

docker-compose stop

อยากจะ start กลับมาทำงานต่อ

docker-compose start

ดูซิ มี container ไหนรันอยู่บ้าง

docker-compose ps

complete repo

https://github.com/chonla/lemp

อ้างอิง:

  • https://www.masterzendframework.com/docker-development-environment/

Leave a Reply

Your email address will not be published. Required fields are marked *