Thật dễ dàng để code PHP mà không cần cài đặt gì lên máy tính của bạn ?

Mở đầu

Ở thời điểm hiện tại mà các hệ thống mới có khuynh hướng sử dụng kiến trúc Microservice, nhà nhà người người nhắc về Docker như một giải pháp hàng đầu để mang lại hiệu năng tốt nhất cho ứng dụng của mình. Docker không chỉ mang lại nhiều giá trị cho các hệ thống trên môi trường Production mà khi ta tận dụng nó cho môi trường Dev, rất nhiều lợi ích được Docker đem lại như:

  • Tạo môi trường đồng bộ giữa các thành viên trong team
  • Đẩy nhanh quá trình giả lập môi trường để bắt đầu code

Sử dụng Docker để xây dựng môi trường phát triển cho ứng dụng Laravel

Docker Compose

Trong những năm qua, Docker trở thành 1 giải pháp thường xuyên được sử dụng để triển khai nhanh các ứng dụng nhờ vào đơn giản hóa việc chạy và triển khai các ứng dụng trong container. Khi chúng ta sử dụng LEMP, ví dụ, với PHP, Nginx, Mysql và Laravel framework, Docker có thể đơn giản hóa quá trình thiết lập.

Docker Compose đã đơn giản hóa hơn nữa quá trình phát triển bằng cách cho phép các nhà phát triển xác định cơ sở hạ tầng của họ, bao gồm các application services, networks và volumes trong một file duy nhất. Docker Compose cung cấp một giải pháp thay thế hiệu quả để chạy nhiều lệnh tạo Docker container.

Trong hướng dẫn này, chúng ta sẽ xây dựng một ứng dụng web Laravel, với Nginx là máy chủ web và MySQL là cơ sở dữ liệu, tất cả bên trong các Docker container. Bạn sẽ xác định toàn bộ cấu hình trong 1 file docker-compose.yml, cùng với các tệp cấu hình cho PHP, MySQL, Redis và Nginx.

Bắt đầu thôiii

Trước tiên chúng ta cần cài đặt Docker và Docker Compose trên máy host trước.

PHP

Chúng ta cần clone Laravel app từ Github về

$ git clone [email protected]:laravel/laravel.git my-laravel
$ cd my-laravel
$ cp .env.example .env
$ sudo chmod -R 777 storage/

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/8.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. Mình chỉ init dự án bằng repository của Laravel từ Github thôi. Còn Composer và PHP sẽ do Docker lo

FROM php:7.4-fpm

# Install dependencies
RUN apt-get update && apt-get install -y \
    build-essential \
    mariadb-client \
    libpng-dev \
    libjpeg62-turbo-dev \
    libfreetype6-dev \
    libonig-dev \
    locales \
    zip \
    jpegoptim optipng pngquant gifsicle \
    vim \
    unzip \
    git \
    curl

# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*

# Install extensions & required packages
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl
RUN docker-php-ext-configure gd --with-freetype --with-jpeg
RUN docker-php-ext-install gd
RUN curl -sS https://getcomposer.org/installer | \
    php -- --install-dir=/usr/local/bin --filename=composer

# Install Xdebug if necessary
ARG XDEBUG=false
RUN if [ $XDEBUG = "true" ] ; then\
        pecl install xdebug;\
        docker-php-ext-enable xdebug;\
        echo "error_reporting = E_ALL" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini;\
        echo "display_startup_errors = On" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini;\
        echo "display_errors = On" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini;\
        echo "xdebug.remote_enable=1" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini;\
    fi ;

# Set new UID for user www-data
RUN usermod -u 1000 www-data

WORKDIR /var/www/
COPY . .

RUN composer install

EXPOSE 9000
CMD ["php-fpm"]

Trong Dockerfile trên có thực thi luôn việc chạy composer install cho project, nên chúng ta cần sử giá trị memory_limit để không gặp lỗi trong quá trình composer install

memory_limit = -1

Nginx

Ta sẽ cần 1 web service để xử lý các request đến và đưa đến cho Laravel xử lý. Ngoài Nginx ta có thể chọn Apache. Trong bài này, mình chọn Nginx.

FROM nginx:latest

ARG PHP_FPM_SERVER=127.0.0.1
ARG PHP_FPM_PORT=9000
COPY deployment/docker/nginx.conf /tmp/nginx.conf
RUN envsubst '$PHP_FPM_SERVER $PHP_FPM_PORT' < /tmp/nginx.conf > /etc/nginx/conf.d/default.conf

EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]

Trong Dockerfile của Nginx mình sử dụng file cấu hình như này

server {
    listen 80 default;
    root /var/www/public;
    error_log /dev/stdout info;
    access_log /dev/stdout;
    location / {
        try_files $uri $uri/ /index.php$is_args$args;
        autoindex off;
        index  index.php;
    }
    location ~ \.php$ {
        set $path_info $fastcgi_path_info;
        fastcgi_index index.php;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include /etc/nginx/fastcgi_params;
        fastcgi_pass $PHP_FPM_SERVER:$PHP_FPM_PORT;
        fastcgi_param SCRIPT_FILENAME $request_filename;
        fastcgi_param PHP_VALUE "upload_max_filesize=50M \n post_max_size=50M";
    }
}

Ở trên các bạn chú ý dòng fastcgi_pass $PHP_FPM_SERVER:$PHP_FPM_PORT: khi có request gửi đến Nginx, Nginx sẽ chuyển request đó tới PHP-FPM đang lắng nghe ở host tên là 127.0.0.1 và port 9000 (do mình cấu hình trong Dockerfile ở trên).

Mysql

Với Mysql chúng ta không cần bổ sung file cấu hình quá nhiều, chỉ cần tạo trước 1 schema db_test cho dự án bằng file SQL thôi

CREATE DATABASE IF NOT EXISTS `db_test`;
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%';

docker-compose.yml

Bên trên là các Dockerfile và file cấu hình cho từng service PHP, Mysql, Nginx, cuối cùng chúng ta cần xây dựng file docker-compose.yml nữa.

version: '2.2'
services:
  nginx:
    container_name: backend-nginx
    build:
      context: .
      dockerfile: deployment/docker/Dockerfile.nginx
      args:
        PHP_FPM_SERVER: php
        PHP_FPM_PORT: 9000
    ports:
      - ${DOCKER_NGINX_EXTERNAL_PORT-8080}:80
    depends_on:
      - php
    links:
      - php

  php:
    container_name: backend-php
    build:
      context: .
      dockerfile: deployment/docker/Dockerfile
      args:
        XDEBUG: "true"
    volumes:
      - /var/www/vendor
      - .:/var/www/
      - ./deployment/docker/php.ini:/usr/local/etc/php/conf.d/php.ini
    environment:
      APP_ENV: local
      PHP_IDE_CONFIG: serverName=ide-debugger-server
      XDEBUG_CONFIG: remote_host=${XDEBUG_REMOTE_HOST:-host.docker.internal} remote_port=9001
    links:
      - mysql
      - redis

  redis:
    container_name: redis
    image: redis:5.0.6
    ports:
      - ${DOCKER_REDIS_EXTERNAL_PORT-6379}:6379

  mysql:
    container_name: mysql
    image: mysql:5.7
    volumes:
      - mysqldata:/var/lib/mysql
      - ./deployment/docker/mysql-database-test.sql:/docker-entrypoint-initdb.d/mysql-database-test.sql
    environment:
      MYSQL_DATABASE: db
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_ALLOW_EMPTY_PASSWORD: "true"
    ports:
      - ${DOCKER_MYSQL_EXTERNAL_PORT-3306}:3306
    command: [ 'mysqld', '--character-set-server=utf8mb4', '--collation-server=utf8mb4_unicode_ci' ]

  phpmyadmin:
    container_name: phpmyadmin
    depends_on:
      - mysql
    image: phpmyadmin/phpmyadmin
    environment:
      PMA_HOST: mysql
    ports:
      - ${DOCKER_PMA_EXTERNAL_PORT-8088}:80

volumes:
  mysqldata:
    driver: local

Vậy là hoàn thiện phần cấu hình, bây giờ bạn chạy

$ docker-compose up

để build image và bật các container lên thôi.

Sau khi chạy tất cả các service bật lên, chúng ta truy cập vào http://localhost:8080/ để xem thành quả

Tham khảo


All Rights Reserved