- vừa được xem lúc

Mình đã docker hóa một ứng dụng Laravel như thế nào?

0 0 94

Người đăng: Le Duc

Theo Viblo Asia

Docker là một công cụ quen thuộc và phổ biến đối với những Developer. Docker giúp chúng ta dựng môi trường phát triển một cách nhanh chóng, thuận tiện và độc lập với môi trường thật, tránh được những xung đột không đáng có. Chính vì những lợi ích trên, nên docker đang được sử dụng ngày càng rộng rãi. Trong bài viết này, mình sẽ hướng dẫn các bạn cách docker hóa một ứng dụng Laravel, hy vọng bài viết này sẽ giúp các bạn hình thành được mindset phải làm những gì khi muốn docker hóa một ứng dụng nào đó. Let's go!!!

1. Chuẩn bị

  • Hệ điều hành mình đang sử dụng là: Ubuntu 18.04.
  • Máy tính cần cài đặt docker và docker-compose.
  • Kiến thức cơ bản về docker, docker-compose và dockerfile.
  • Source code laravel, các bạn có thể clone tại đây: https://github.com/laravel/laravel
  • Cấu trúc thư mục sẽ như sau:

  • Thư mục .docker là nơi lưu Dockerfile, data được mount từ container.
  • Thư mục src là nơi lưu source code, và ở trong thư mục này sẽ có chứa sẵn source code Laravel, các bạn cần copy source code vào thư mục này.

2. Dockerfile

Trước khi tiến docker hóa một ứng dụng nào đó, chúng ta cần xác định xem ứng dụng đó cần những gì, cụ thể ở đây đối với một ứng dụng Laravel. Để có thể chạy được cần những thành phần sau:

  • Webserver: Sử dụng Nginx.
  • Database: Sử dụng MySQL.
  • PHP-FPM: Trình phiên dịch của PHP.

Sau khi xác định được những thành phần cần thiết, chúng ta sẽ lựa chọn image phù hợp hoặc tự custom image bằng cách sử dụng Dockerfile.

Đầu tiên webserver, cụ thể ở đây là Nginx:

  • Bởi vì đối với Nginx, mình sẽ cần custom lại một vài chỗ nên là sẽ không sử dụng trực tiếp image Nginx để build lên Container, mà mình sẽ tạo ra một Dockerfile để build lên image riêng dựa trên image Nginx.

  • Ở trong thư mục con conf.d, mình tạo một file là default.conf, đây là file sẽ config Nginx ở trong container, với nội dung như sau:

server { listen 80; index index.php index.html; server_name _; root /var/www/html/public; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass php-fpm:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; }
}
  • Tiếp theo mình tạo ra một Dockerfile ở trong thư mục .docker/nginx, với nội dung như sau:
# Sử dụng image nginx:1.19-alpine
FROM nginx:1.19-alpine # Copy toàn bộ nội dung ở trong default.conf vào file default.conf trong container
ADD ./.docker/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf # Tạo thư mục /var/www/html
RUN mkdir -p /var/www/html

Tiếp theo, là PHP-FPM

  • Đối với PHP-FPM, mình sẽ tạo ra một Dockerfile ở trong thư mục .docker/php-fpm với nội dung như sau:
# Sử dụng image php:8.0-fpm-alpine
FROM php:8.0-fpm-alpine LABEL maintainer="DucLS <_@.com>" ARG DEBIAN_FRONTEND=noninteractive # Cài đặt những thư viện cần thiết
RUN docker-php-ext-install \ bcmath \ pdo_mysql # Tạo thư mục /var/www/html
RUN mkdir -p /var/www/html # Copy toàn bộ file trong thư mục ./src ở máy local vào trong thư mục /var/www/html ở trong container
COPY ./src /var/www/html
  • Tại sao mình lại sử dụng image php:8.0-fpm-alpine và tại sao mình lại cài đặt những thư viện trên?
  • Bởi vì, đối với một ứng dụng Laravel sẽ yêu cầu hệ thống cần có những thư viện sau:

  • Vậy làm sao để xác định xem những thư viện nào cần cài trong quá trình build image? Mình đọc Dockerfile trên Dockerhub: https://hub.docker.com//php , cụ thể ở đây mình đọc Dockerfile của image php:8.0-fpm-alpine: https://sal.vn/qveeZh . Và thấy 2 thư viện chưa được cài là bcmath và pdo_mysql. Đối với những ứng dụng khác các bạn có thể áp dụng thử cách này để cài đặt những thư viện cần thiết trong quá trinh build image.

Đối với Mysql, thì mình sử dụng trực tiếp image từ Dockerhub, nên sẽ không cần tạo Dockerfile.

Ngoài 3 thành phần chính trên, mình sẽ sử dụng thêm một container khác, và đặt tên là Workspace, với container này mình sẽ cài đặt Composer, Git, Nano, Vim,... Và mình sẽ thao tác với app Laravel thông qua container này.

Workspace

  • Mình sẽ tạo ra Dockerfile ở trong thư mục .docker/workspace, với nội dung như sau:
FROM composer:2.0 FROM php:8.0 LABEL maintainer="DucLS <_@.com>" ARG DEBIAN_FRONTEND=noninteractive # Cài đăt composer
COPY --from=composer:2.0 /usr/bin/composer /usr/bin/composer RUN apt-get update && apt-get install -y \ software-properties-common locales # Cài đặt các tool cần thiết
RUN apt-get update && apt-get install -y \ git \ curl \ vim \ nano \ net-tools \ pkg-config \ iputils-ping \ apt-utils \ zip \ unzip # Cài đặt các thư viện cần thiết
RUN docker-php-ext-install \ bcmath \ pdo_mysql # Cài đặt nodejs
RUN curl -sL https://deb.nodesource.com/setup_14.x | bash RUN apt-get install -y nodejs #Tạo thư mục /var/www/html
RUN mkdir -p /var/www/html #Copy toàn bộ source code ở folder ./src ở local vào thư mục /var/www/html trong container
COPY ./src /var/www/html

3. Docker-compose

Sau khi đã chuẩn bị Dockerfile cho các thành phần cần thiết, mình tiến hành build và run multi-container bằng cách sử dụng docker-compose. MÌnh tạo 1 file docker-compose.yml với nội dung như sau:


version: "3.0" services: webserver: build: context: . dockerfile: .docker/nginx/Dockerfile container_name: laravel_nginx volumes: - ./src:/var/www/html - .docker/nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf - .docker/data/logs/nginx:/var/log/nginx ports: - 8080:80 depends_on: mysql php-fpm php-fpm: build: context: . dockerfile: .docker/php-fpm/Dockerfile container_name: laravel_php-fpm volumes: - ./src:/var/www/html mysql: image: mysql:8.0 container_name: laravel_mysql volumes: - .docker/data/db:/var/lib/mysql environment: MYSQL_DATABASE: demo MYSQL_ROOT_PASSWORD: root workspace: build: context: . dockerfile: .docker/workspace/Dockerfile container_name: laravel_workspace volumes: - ./src:/var/www/html working_dir: /var/www/html tty: true 
  • Để duy trì data trong container không bị mất khi tắt container, thì mình sẽ sử dụng volumes, để mount trực tiếp data trong container ra ngoài máy local, và source code thay đổi ở ngoài local cũng sẽ thay đổi trong container.
  • Vậy các service trên sẽ nói chuyện với nhau như thế nào?
  • Nginx nói chuyện với PHP-FPM thông qua port 9000, ở image php:8.0-fpm-alpine đã mở sẵn port 9000, nên mình không cần sử dụng expose trong docker-compose ở service php-fpm nữa. Và container chạy php-fpm mình có đặt tên service là php-fpm, chính vì vậy nội dung file default.conf ở trong thư mục .docker/nginx/conf.d là:

server { listen 80; index index.php index.html; server_name _; root /var/www/html/public; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass php-fpm:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; }
} 
  • Ở dòng fastcgi_pass php-fpm:9000 để chỉ rõ Nginx sẽ giao tiếp với PHP-FPM thông qua port 9000 ở trong Docker. Nếu như các bạn không muốn đặt tên service chạy container php-fpm như mình, thì các bạn phải sửa lại dòng fastcgi_pass, ví dụ như mình đăt tên service là fpm, thì mình sẽ phải sửa lại là: fastcgi_pass fpm:9000.

Ngoài docker-compose.yml, mình sẽ tạo một file là .dockerignore, nhưng thư mục trong file này sẽ được bỏ qua trong quá trình build và run docker, file này có nội dung như sau:

.docker/data/

4. Docker-compose up

Sau khi đã build xong file docker-compose.yml, thì mình sẽ tiến hành build các container bằng command: docker-compose build

Sau khi build xong, mình sẽ khởi chạy container bằng command: docker-compose up

Sau khi khởi chạy thành công, các bạn cần làm các bước sau:

  • Copy nôi dụng file .env.example sang file .env: cp .env.example .env.
  • Config file .env với nội dung sau:

APP_NAME=Laravel
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost LOG_CHANNEL=stack
LOG_LEVEL=debug DB_CONNECTION=mysql
# Bởi vì container chạy MySql mình đặt tên là laravel_mysql
DB_HOST=laravel_mysql # Port 3306 đã được mở sẵn trong container DB_PORT=3306 # Tên DB mình config trong docker-compose
DB_DATABASE=demo
DB_USERNAME=root
DB_PASSWORD=root BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120 MEMCACHED_HOST=127.0.0.1 REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379 MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME="${APP_NAME}" AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET= PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1 MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" 
  • Tiếp theo để generate key cho app Laravel, chạy câu lệnh sau: docker container exec laravel_workspace php artisan key:generate
  • Sau đó migrate database bằng cách: docker container exec laravel_workspace php artisan migrate
  • Chạy composer để cài đặt các thư viện cần thiết: docker container exec laravel_workspace composer install
  • Và cuối cùng là cấp quyền cho thư mục storage: chmod -R 777 ./src/storage

Sau khi làm các bước trên, dùng trình duyệt vào localhost:8080, và xem kết quả:

Vậy là đã docker hóa xong một ứng dụng Laravel ?. Thay đổi source code ở máy local, thì source code ở trong container cũng thay đổi theo, nên là các bạn không cần khởi tạo lại container mỗi lần thay đổi source code nữa nhé. Ví dụ:

5. Lời kết

Hy vọng bài viết này sẽ giúp các bạn có một mindset về docker hóa một ứng dụng nào đó. Khi bắt đầu có thể gặp rất nhiều lỗi, hy vọng các bạn đừng bỏ cuộc mà hãy sử dụng Google và Stackoverflow để tìm giải pháp. Chúc các bạn thành công! ???

Bình luận

Bài viết tương tự

- vừa được xem lúc

Cài đặt WSL / WSL2 trên Windows 10 để code như trên Ubuntu

Sau vài ba năm mình chuyển qua code trên Ubuntu thì thật không thể phủ nhận rằng mình đã yêu em nó. Cá nhân mình sử dụng Ubuntu để code web thì thật là tuyệt vời.

0 0 376

- vừa được xem lúc

Phần 1: Giới thiệu về Kubernetes

Kubernetes là gì. Trang chủ: https://kubernetes.io/. Ai cần Kubernetes.

0 0 80

- vừa được xem lúc

Docker: Chưa biết gì đến biết dùng (Phần 1- Lịch sử)

1. Vì sao nên sử dụng. . .

0 0 89

- vừa được xem lúc

Docker - những kiến thức cơ bản phần 1

Giới thiệu. Nếu bạn đang làm ở một công ty công nghệ thông tin, chắc rằng bạn đã được nghe nói về Docker.

0 0 65

- vừa được xem lúc

Docker: Chưa biết gì đến biết dùng (Phần 2 - Dockerfile)

1. Mở đầu.

0 0 53

- vừa được xem lúc

Docker: Chưa biết gì đến biết dùng (Phần 3: Docker-compose)

1. Mở đầu. . .

0 0 106