Trong bài viết này chúng ta sẽ tạo dockerfile build 2 image là laravel-nginx, laravel-fpm push lên AWS ECR, để phục vụ cho việc deploy project laravel lên AWS ECS.
Tạo project laravel có cấu trúc thư mục như sau
Cấu trúc file docker-compose.yml cấu hình khi sử dụng docker compose
version: '3.4'
networks:
  backend:
    driver: bridge
services:
  nginx:
    #image: 056663857946.dkr.ecr.us-east-1.amazonaws.com/laravel-nginx
    build:
      context: .
      dockerfile: docker/app/Dockerfile.nginx
      args:
        PHP_FPM_SERVER: app
        PHP_FPM_PORT: 9000
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./docker/nginx/conf.d:/etc/nginx/conf.d
      - .:/var/www/
    links:
      - app
    depends_on:
      - app
    networks:
      - backend
  app:
    #image: 056663857946.dkr.ecr.us-east-1.amazonaws.com/laravel-fpm
    build:
      context: .
      dockerfile: docker/app/Dockerfile
    volumes:
      - .:/var/www/
    links:
      - db
      - redis
      - minio
    networks:
      - backend
  db:
    image: mysql:5.7
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci --skip-character-set-client-handshake
    ports:
      - "3389:3306"
    volumes:
      - ./docker/mysql/init/init-databases.sql:/docker-entrypoint-initdb.d/init-databases.sql
      - dbdata:/var/lib/mysql
    environment:
      MYSQL_DATABASE: application
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_PASSWORD: secret
      MYSQL_USER: mysql
    networks:
      - backend
  redis:
    image: redis:latest
    restart: always
    volumes:
      - ./docker/logs/redis:/var/log/redis
    ports:
      - "6379:6379"
    networks:
      - backend
    command: redis-server --appendonly yes
  minio:
    image: minio/minio
    ports:
      - "9000:9000"
      - "9001:9001"
    volumes:
      - ./docker/minio:/data
    tty: true
    networks:
      - backend
    environment:
      MINIO_ACCESS_KEY: minio
      MINIO_SECRET_KEY: minio123
      MINIO_REGION_NAME: us-west-2
    command: server /data --console-address ":9001"
volumes:
  dbdata:
Tạo dockerFile docker/app/Dockerfile.nginx build image nginx, sử dụng phiên bản nginx mới nhất.
FROM nginx:latest
ARG PHP_FPM_SERVER=127.0.0.1
ARG PHP_FPM_PORT=9000
COPY docker/nginx/nginx.conf /tmp/nginx.conf
RUN envsubst '$PHP_FPM_SERVER $PHP_FPM_PORT' < /tmp/nginx.conf > /etc/nginx/conf.d/default.conf
# COPY . /var/www
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]
Tạo file config nginx docker/nginx/nginx.conf dùng để cấu hình nginx, php-fpm
server {
    listen 80 default;
    root /var/www/public;
    error_log  /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;
    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";
    }
}
Chú ý: fastcgi_pass cho ecs loại fargate sẽ mặc định là localhost:9000 loại ecr sẽ maping theo container theo dạng containerName:post ví dụ app:9000
Build và push nginx image lên ECR
// Đăng nhập AWS ECR
aws ecr get-login-password --region [region] | docker login --username AWS --password-stdin [account-id].dkr.ecr.[region].amazonaws.com
// Create ECR repo
aws ecr create-repository --repository-name laravel-nginx --region us-east-1
// Build image với docker
// Truy cập vào thư mục gốc của dự án, run command
docker build -t laravel-nginx -f docker/app/Dockerfile.nginx .
// Tạo tag cho image
docker tag laravel-nginx:latest [account-id].dkr.ecr.us-east-1.amazonaws.com/laravel-nginx:latest
// push image to ECR
docker push [account-id].dkr.ecr.us-east-1.amazonaws.com/laravel-nginx:latest
Tạo dockerFile sử dụng php:8.1.0-fpm để chạy project sử dụng laravel 9 trong file docker/app/Dockerfile.nginx
FROM php:8.1.0-fpm AS prod
 
# Install system dependencies
RUN apt-get update && apt-get install -y \
    build-essential \
    mariadb-client \
    libpng-dev \
    libjpeg62-turbo-dev \
    libfreetype6-dev \
    libonig-dev \
    locales \
    libzip-dev \
    zip \
    jpegoptim optipng pngquant gifsicle \
    vim \
    unzip \
    git \
    curl \
    libsodium-dev \
    pkg-config
# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
# Install PHP extensions
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
# Get latest Composer
RUN curl -sS https://getcomposer.org/installer | \
    php -- --install-dir=/usr/local/bin --filename=composer
# Install php redis
RUN pecl install -o -f redis \
&&  rm -rf /tmp/pear \
&&  docker-php-ext-enable redis
# Set new UID for user www-data
#RUN usermod -u 1000 www-data
# Set permission
# RUN adduser www-data root
# Set new UID for user www-data
RUN usermod -u 1000 www-data
# Set working directory
WORKDIR /var/www
COPY . .
# Build image deploy ecs
RUN composer install
RUN chmod -R 777 storage
# RUN chown -R www-data:www-data \
#     /var/www/storage \
#     /var/www/bootstrap/cache
Chú ý cần chạy composer install, chmod cho thư mục storage, và copy toàn bộ source laravel vào image thì mới chạy được trên AWS ECS.
Build và push laravel-fpm image lên ECR
// Đăng nhập AWS ECR
aws ecr get-login-password --region [region] | docker login --username AWS --password-stdin [account-id].dkr.ecr.[region].amazonaws.com
// Create ECR repo
aws ecr create-repository --repository-name laravel-fpm --region us-east-1
// Build image với docker
// Truy cập vào thư mục gốc của dự án, run command
docker build -t laravel-fpm -f docker/app/Dockerfile .
// Tạo tag cho image
docker tag laravel-fpm:latest [account-id].dkr.ecr.us-east-1.amazonaws.com/laravel-fpm:latest
// push image to ECR
docker push [account-id].dkr.ecr.us-east-1.amazonaws.com/laravel-fpm:latest
Ngoài sử dụng docker, chúng ta cũng có thể sử dụng docker-compose để build and push image to ECR. Bằng cách thêm ECR URI vào file docker-compose.yml
version: '3.4'
networks:
  backend:
    driver: bridge
services:
  nginx:
    image: 056663857946.dkr.ecr.us-east-1.amazonaws.com/laravel-nginx
    build:
      context: .
      dockerfile: docker/app/Dockerfile.nginx
      args:
        PHP_FPM_SERVER: app
        PHP_FPM_PORT: 9000
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./docker/nginx/conf.d:/etc/nginx/conf.d
      - .:/var/www/
    links:
      - app
    depends_on:
      - app
    networks:
      - backend
  app:
    image: 056663857946.dkr.ecr.us-east-1.amazonaws.com/laravel-fpm
    build:
      context: .
      dockerfile: docker/app/Dockerfile
    volumes:
      - .:/var/www/
    links:
      - db
      - redis
      - minio
    networks:
      - backend
volumes:
  db-data:
Command build and push
// Đăng nhập ECR
aws ecr get-login-password --region [region] | docker login --username AWS --password-stdin [account-id].dkr.ecr.[region].amazonaws.com
// Build laravel-nginx
docker-compose build nginx
// Push laravel-nginx to ecr
docker-compose push nginx
// Build laravel-fpm
docker-compose build app
// Push laravel-fpm to ecr
docker-compose push app
Như vậy lả chúng ta đã tạo thành công 2 image laravel-nginx, laravel-fpm trên AWS ECR.