Create docker image to AWS ECR

  • September 18, 2022
  • 725

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.

Laravel structure

Tạo project laravel có cấu trúc thư mục như sau
Laravel structure

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:


Create dockerFile for nginx

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 and push nginx image to ECR

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

Create dockerFile for laravel-fpm

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 and push laravel-fpm image to ECR

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

Build and push image to ECR with docker compose

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.
Ecr repo