Cài đặt môi trường Docker cho Laravel 2019
White

Trần Mỹ viết ngày 03/01/2020

Xin chào mọi người. Hôm nay mình xin chia sẻ về cách thiết lập môi trường Docker cho project sử dụng Laravel của cá nhân mình. Hi vọng sẽ có ích với mọi người.

Trước đây mình cũng đã có một bài chia sẻ tương tự ở đây
https://kipalog.com/posts/Thu-cai-dat-moi-truong-docker-cho-laravel
tuy nhiên hiện tại version laravel cũng hơi cũ rồi nên mình cập nhật lại ở bài viết này, cộng thêm thay đổi về cấu trúc project cho dễ cài đặt và coding hơn.

Ngoài ra thì với những bạn lần đầu cấu trúc môi trường thì các bạn có tham khảo một framework có sẵn laravel và docker là Laradock, đây là một repository khá hot về cài đặt môi trường cho project sử dụng PHP với Docker, sử dụng luôn laradock có thể tiết kiệm nhiều thời gian và công sức hơn rất nhiều. Bài viết của mình là tự xây dựng từ đầu sẽ mất công hơn 1 chút.

Thông tin về môi trường Host

Host tức là môi trường máy mà mình thao tác, thực hiện command trên đó. Môi trường khác nhau ví dụ như Windows/Linux cũng có gây 1 chút ảnh hưởng nên mình ghi lại để các bạn đối chiếu.

OS

MacOS High Sierra 10.13.6

Docker

$docker -v
Docker version 19.03.5, build 633a0ea

Docker Compose

$docker-compose -v
docker-compose version 1.24.1, build 4667896b

Môi trường dự định cài đặt

Webserver

Nginx 1.0

Database

mysql 8.0

PHP

PHP:7.4-FPM

Cấu trúc

Sau khi cài đặt xong, proẹct sẽ có cấu trúc như sau, các bạn có thể xác nhận trước để dễ hình dung.

|-- app # Docker image cho Laravel, chứa source code về Laravel
|-- composer # Docker image cho composer
|-- db # Docker image cho db
|-- docker-compose.yml 
|-- web # Docker image cho web server

Bạn có thể hình dung sau khi cài đặt môi trường sẽ như sau :
alt text

Browser tương tác với hệ thống qua thành phần đầu tiên là webserver Nginx, từ đây Nginx sẽ điều hướng đến App. Phía app xử lý và trao đổi dữ liệu với database nếu cần thiết, cuối cùng là trả về response về lại Nginx và trả về browser.

Cài đặt

1. Tạo project Laravel

1.1. Tạo một directory trống

Mình đặt tên là docker_laravel_2019, bạn có thể đặt với tên tuỳ thích

$ mkdir docker_laravel_2019
$ cd docker_laravel_2019

1.2. Tạo project Laravel mới

Ta sẽ tạo một project laravel mới bằng composer.

Thông thường thì ta sẽ cần cài composer trên máy host và dùng composer để tải về project laravel mới như hướng dẫn trên offical https://laravel.com/docs/6.x/installation#installing-laravel . Tuy nhiên với mình thì so với việc dùng docker thì việc cài đặt composer nói riêng và quản lý version php hay composer trên máy host nói chung cũng hơi mất công một chút, nên mình tạo một docker container riêng cho việc này, chứa composer và install với cấu hình theo ý mình.

1.2.1. Tạo dir composer

Theo đó, mình tạo một directory mới và build một docker image về composer mới.

$ mkdir composer

Đến đây mình tạo dockerfile về composer docker image tại composer/composer.dockerfile

1.2.2. Tạo docker image composer (php)

https://github.com/mytv1/docker_laravel_2019/blob/master/composer/composer.dockerfile
composer/composer.dockerfile

FROM php:7.4-fpm

RUN apt-get update && apt-get install -y libzip-dev

# Extension zip for laravel
RUN docker-php-ext-install zip 

# Install composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

RUN composer global require laravel/installer

Mình dùng base image là php:7-4-fpm là bản mới nhất của php thay vì image của composer có sẵn.

Ngoài tải bản thân composer thì mình cũng require sẵn laravel/installer, laravel installer cần thêm libzip-devzip nên mình install thêm vào ở trên. Laravel installer này mình sẽ dùng để tải về fresh project laravel về.

1.2.3. Build composer docker image

$ docker build -t localcomposer -f ./composer/composer.dockerfile ./composer

1.2.4. Dùng docker container composer này tạo fresh laravel directory

Build thành công, ta dùng image này để tạo project laravel mới tương tự như laravel new blog

$ docker run -it -v $(pwd):/var/www/html localcomposer:latest /root/.composer/vendor/bin/laravel new app

Tạo thành công, ta sẽ thấy cấu trúc directory hiện tại như sau

|-- app
|-- composer
    |-- composer.dockerfile

1.3. Cấu trúc docker container Nginx

1.3.1. Tạo directory mới

$ mkdir web

1.3.2. Tạo file cấu hình nginx

Tạo web/vhost.conf

https://github.com/mytv1/docker_laravel_2019/blob/master/web/vhost.conf

server {
      listen 80;
      index index.php index.html;
      root /var/www/public;
      error_log  /var/log/nginx/error.log;
      access_log /var/log/nginx/access.log;
      proxy_set_header HTTP_AUTHORIZATION $http_authorization;

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

      location ~ \.php$ {
          fastcgi_split_path_info ^(.+\.php)(/.+)$;
          fastcgi_pass app:9000;
          include fastcgi_params;
          fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
          fastcgi_param PATH_INFO $fastcgi_path_info;
          sendfile off;
      }
}

Trong đó có 1 số config cần chú ý như sau:

  • listen 80 : Webserver lắng nghe ở port 80
  • fastcgi_pass app:9000: Cấu hình địa chỉ FastCGI server với host là app (mình define trong docker-composer.yml sau này), và port là 9000 (default export port của docker container)
  • root /var/www/public; : Những request đến file ngoài .php như css hay js trỏ thẳng đến public, đây là directory sau này sẽ mount từ ./app/public với config trong docker-composer.yml
Cấu trúc docker iamge nginx

Tạo web/web.dockerfile
https://github.com/mytv1/docker_laravel_2019/blob/master/web/web.dockerfile

FROM nginx:1.10
ADD vhost.conf /etc/nginx/conf.d/default.conf

Base image là nginx:1.10, khi tạo image ta copy vhost.conf vào địa chỉ cấu hình của nginx với lệnh ADD

Đến đây ta có cấu trúc directory như sau

|-- app
|-- composer
|-- web
    |-- vhost.conf
    |-- web.dockerfile

1.4. Tạo cấu hình Mysql

1.4.1. Tạo directory mới

$ mkdir db

1.4.2. Thiết lập cho database

Tạo ./db/my.cnf
https://github.com/mytv1/docker_laravel_2019/blob/master/db/my.cnf

[mysqld]
default-authentication-plugin = mysql_native_password

Mình dùng mysql:8.0, ở phiên bản này thì default authentication-plugin không phải là mysql_native_password mà là caching_sha2_password, nói cách khác nếu ta đơn thuần access từ laravel bởi user-password có thể sẽ có báo lỗi không support authentication-plugin này.

Do đó mình thêm config này để laravel vẫn có thể access thường bằng user-password như trước.

Mình sẽ dùng image có sẵn của docker về mysql, và mount file config này vào đó.

Đến đây ta có cấu trúc directory như sau

|-- app
|-- composer
|-- web
|-- db
    |-- my.conf 

1.5. Cấu trúc docker container Laravel

1.5.1. Tạo dockerfile ./app/app.dockerfile

https://github.com/mytv1/docker_laravel_2019/blob/master/app/app.dockerfile

FROM php:7.4-fpm

RUN apt-get update && apt-get install -y libzip-dev

# Extension mysql driver for mysql
RUN docker-php-ext-install pdo_mysql mysqli

Base image tương tự với composer, mình chọn là php:7.4-fpm

1.5.2. Install vendor

docker run -v $(pwd)/app:/var/www/html localcomposer:latest composer install

Ta dùng composer build trên local vừa nãy để install vendor cho laravel với câu lệnh trên

1.5.3. Sửa lại thông tin biến môi trường

Ta sửa lại thông tin trong ./app/.env 2 biến sau

DB_HOST=127.0.0.1
DB_PASSWORD=

DB_HOST=database
DB_PASSWORD=secret
  • DB_HOST : database là tên host database mà laravel sẽ trỏ đến mà ta sẽ define trong docker-composer.yml sau này, thông thường là localhost nhưng lần này ta dùng docker nên sẽ cần chỉ định tên host khác.
  • DB_PASSWORD : password dùng để access đến database, tương tự ta sẽ chỉ định trong docker-composer.yml

Đến đây ta có cấu trúc directory như sau

|-- app
    |-- ....
    |-- .env    
    |-- app.dockerfile
    |-- ....
|-- composer
|-- web
|-- db

1.6. Tạo docker-compose.yml

docker-compose.yml là file cấu hình cho các docker-container của ta hoạt động.
Mình đề xuất nội dung như sau :

Tạo ./docker-compose.yml
https://github.com/mytv1/docker_laravel_2019/blob/master/docker-compose.yml

version: '3'
services:

  # The Application
  app:
    build:
      context: ./app/
      dockerfile: app.dockerfile
    working_dir: /var/www
    volumes:
      - ./app/:/var/www/

  # The Web Server
  web:
    build:
      context: ./web/
      dockerfile: web.dockerfile
    working_dir: /var/www
    volumes:
      - ./web/:/var/www/
      - ./app/public:/var/www/public
    ports:
      - 8080:80

  # The Database
  database:
    image: mysql:8.0
    volumes:
      - ./db/dbdata:/var/lib/mysql
      - ./db/my.cnf:/etc/mysql/conf.d/my.cnf
    command: ['--character-set-server=utf8mb4', '--collation-server=utf8mb4_unicode_ci','--default-authentication-plugin=mysql_native_password']
    environment:
      MYSQL_DATABASE: laravel
      MYSQL_ROOT_PASSWORD: secret
    ports:
        - "33061:3306"

volumes:
  dbdata:

Như các bạn đã thực hiện ở trước đó nên chắc cũng đã biết, cấu trúc các docker container của mình như sau

  • app : docker container chứa laravel, các xử lý về laravel thực hiện ở đây. Có một config cần chú ý là - ./app/:/var/www/, ở đây mình đã mount app đến entry point của server là /var/www
  • web : docker container chứa proxy server nginx, các request đến ban đầu sẽ được tiếp nhận ở đây và chuyển đến app
  • database : docker-container chứa database, cụ thể là mysql

Đến đây ta có cấu trúc directory như sau :

|-- app
|-- composer
|-- web
|-- db
|-- docker-compose.yml

2. Chạy project

Đến đây ta đã cấu trúc xong môi trường Docker cho Laravel! Chúng ta sẽ chạy lên thử với câu lệnh

$ docker-compose up

Hi vọng là các bạn có thể thấy ở http://0.0.0.0:8080 hiện ra như sau

alt text

Vậy là đến đây cài đặt môi trường đã hoàn thành! Ta có thể bắt đầu coding các tính năng khác cho project laravel.

(Option) Kiểm tra kết nối với cơ sở dữ liệu

Hiện được trang index laravel ở trên cũng chưa hẳn là kết nối đến database thành công. Ta sẽ kiểm tra lại bằng migrate

$docker-compose exec app php artisan migrate --seed

Câu lệnh yêu cầu laravel chạy migrate các bảng mặc định (về auth) kèm theo dữ liệu tạo sẵn (seeding) kiểu như master data

Kết quả khi mình chạy như sau

Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (0.04 seconds)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (0.03 seconds)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (0.02 seconds)
Database seeding completed successfully.

Nếu chạy không có lỗi gì tức là kết nối đến database là bình thường!

3. Source code

Mình đã đưa source code lên https://github.com/mytv1/docker_laravel_2019, các bạn có thể tham khảo cụ thể trên đó.

Kết

Hi vọng bài viết của mình đã cung cấp được cho các bạn các kiến thức hữu ích về cấu trúc project Laravel bằng Docker. Cảm ơn và hẹn gặp lại các bạn ở các bài viết sau.

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Trần Mỹ

10 bài viết.
101 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
43 11
XIn chào mọi người. Thời gian gần đây mình có tìm hiểu về blockchain và golang. Mình viết bài viết này với mục đích chia sẻ và tổng hợp những kiến...
Trần Mỹ viết gần 3 năm trước
43 11
White
34 9
Xin chào mọi người. Thời gian ngắn gần đây mình có tìm hiểu 1 chút về Bitcoin và Blockchain, và để củng cố kiến thức thu nạp được mình quyết định ...
Trần Mỹ viết gần 3 năm trước
34 9
White
17 1
Xin chào mọi người. Đây là phần 2 trong bài viết về xây dựng blockchain đơn giản với golang của mình. Ở (Link) mình đã trình bày về việc xây dựng...
Trần Mỹ viết gần 3 năm trước
17 1
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
10 bài viết.
101 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!