Tìm hiểu các bước để build server sử dụng aws beanstalk docker ecs amazon linux 2023. Build server với beanstalk giúp tiết kiệm thời gian, dễ dàng nâng cấp và bảo trì cho hệ thống của bạn.
Truy cập vào service beanstalk trên aws, tạo một môi trường để chạy ứng dụng web hoặc worker, flatform sử dụng là docker, sử dụng ecs 2023, sau đó cấu hình các thông tin cần thiết cho server của bạn. Chúng ta sẽ sử dụng docker để chạy application.
Định nghĩa các container sử dụng để chạy các service của bạn trong file Dockerrun.aws.json
để trong thư mục root.
{
"AWSEBDockerrunVersion": 2,
"volumes": [
{
"name": "app",
"host": {
"sourcePath": "/var/app/current/app"
}
},
{
"name": "nginx-proxy-conf",
"host": {
"sourcePath": "/var/app/current/docker/nginx/dev/conf.d"
}
},
{
"name": "app-logs",
"host": {
"sourcePath": "/var/app/support/logs"
}
},
{
"name": "supervisord-conf",
"host": {
"sourcePath": "/var/app/current/docker/phpfpm/supervisord-app.ini"
}
},
{
"name": "app2",
"host": {
"sourcePath": "/var/app/current/app2"
}
},
{
"name": "app2-logs",
"host": {
"sourcePath": "/var/app2/support/logs"
}
},
],
"containerDefinitions": [
{
"name": "app",
"image": "AWS_ACCOUNT_ID.dkr.ecr.AWS_DEFAULT_REGION.amazonaws.com/DOCKER_IMAGE_NAME:DOCKER_IMAGE_VERSION",
"essential": true,
"memory": 256,
"mountPoints": [
{
"sourceVolume": "app",
"containerPath": "/var/www/html/app"
},
{
"sourceVolume": "app-logs",
"containerPath": "/var/www/html/app/logs"
},
{
"sourceVolume": "supervisord-conf",
"containerPath": "/etc/supervisor.d/supervisord.ini",
"readOnly": true
}
]
},
{
"name": "app2",
"image": "AWS_ACCOUNT_ID.dkr.ecr.AWS_DEFAULT_REGION.amazonaws.com/DOCKER_IMAGE_NAME_APP2_DOCKER_VERSION",
"essential": false,
"memory": 256,
"mountPoints": [
{
"sourceVolume": "app2",
"containerPath": "/var/www/html/app2"
},
{
"sourceVolume": "app2-logs",
"containerPath": "/var/www/html/app2/logs"
}
]
},
{
"name": "nginx-proxy",
"image": "nginx:1.19.2-alpine",
"essential": true,
"memory": 128,
"portMappings": [
{
"hostPort": 80,
"containerPort": 80
},
{
"hostPort": 81,
"containerPort": 81
}
],
"links": [
"app",
"app2",
],
"mountPoints": [
{
"sourceVolume": "app",
"containerPath": "/var/www/html/app"
},
{
"sourceVolume": "app2",
"containerPath": "/var/www/html/app2"
},
{
"sourceVolume": "awseb-logs-nginx-proxy",
"containerPath": "/var/log/nginx"
},
{
"sourceVolume": "nginx-proxy-conf",
"containerPath": "/etc/nginx/conf.d"
}
]
}
]
}
Tài liệu tham khảo:
https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_docker_v2config.htmlTạo file config global config.global.yml
global:
application_name: APPLICATIONNAME
default_region: APPLICATION_REGION
Tạo các config cho elastic beanstalk trong thư mục .ebextensions
Tạo config cho load balancer trong file .ebextensions/00.network-load-balancer.config
Resources:
AWSEBV2LoadBalancer:
Properties:
LoadBalancerAttributes:
- Key: idle_timeout.timeout_seconds
Value: 600
Type: 'AWS::ElasticLoadBalancingV2::LoadBalancer'
AWSEBV2LoadBalancerTargetGroup:
Properties:
TargetGroupAttributes:
- Key: stickiness.enabled
Value: true
Type: 'AWS::ElasticLoadBalancingV2::TargetGroup'
option_settings:
aws:elasticbeanstalk:environment:process:default:
DeregistrationDelay: '20'
HealthCheckInterval: '30'
HealthCheckPath: /health.html
HealthCheckTimeout: '5'
HealthyThresholdCount: '3'
UnhealthyThresholdCount: '5'
Port: '80'
Protocol: HTTP
StickinessEnabled: 'true'
StickinessLBCookieDuration: '43200'
Tài liệu tham khảo:
https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/environments-cfg-alb.html
Config target group trong file .ebextensions/00.target-group.config
option_settings:
# Define the app 2 process listening on port 81
aws:elb:listener:81:
ListenerProtocol: HTTP
InstanceProtocol: HTTP
InstancePort: 81
Rules: app2
aws:elasticbeanstalk:environment:process:app2:
HealthCheckPath: /
Port: '81'
Protocol: HTTP
StickinessEnabled: true
StickinessLBCookieDuration: 86400
aws:elbv2:listenerrule:app2:
HostHeaders: app2.com
Priority: 2
Process: app2
Tài liệu tham khảo:
https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/environments-cfg-alb.html
Kiểm tra crontab trong khi deploy, nếu trong quá trình deploy có crontab đang chạy thì chờ chạy xong rồi mới deploy
. Tạo file .ebextensions/02.crontab.config
container_commands:
65_01_wait_for_php_cli_not_running:
command: |
# Retrieve the Docker container ID of the PHP image running in the instance
# Use the image identifier in the form of `AWS_ACCOUNT_ID.dkr.ecr.AWS_REGION.amazonaws.com/IMAGE_NAME:IMAGE_VERSION`
CONTAINER_ID=`docker ps -q --filter 'ancestor=AWS_ACCOUNT_ID.dkr.ecr.AWS_DEFAULT_REGION.amazonaws.com/DOCKER_IMAGE_NAME:DOCKER_IMAGE_VERSION'`
# If no container ID is found (e.g., during the first deployment), assume no PHP processes are running and exit successfully
if [ -z "${CONTAINER_ID}" ]; then
exit 0
fi
# Backup the current crontab for the webapp user in case it needs to be restored later
crontab -u webapp -l > .crontab || true
# Remove the existing crontab for the webapp user to avoid deployment conflicts
# This will be reconfigured in other container commands
crontab -u webapp -r || true
# Wait for any PHP CLI processes to stop running in the container
# Retry with increasing intervals (1, 1, 5, 10, 20, 30, 60, 100 seconds)
for interval in 1 1 5 10 20 30 60 100; do
# Check if any PHP processes are running using `pidof php`
# `pidof` exits with code 0 if a process is found, otherwise with code 1
docker exec $CONTAINER_ID bash -c "pidof php > /dev/null 2>&1"
if [ "$?" != "0" ]; then
# If no PHP processes are found, exit successfully
exit 0
fi
# Wait for the specified interval before retrying
sleep $interval
done
# If PHP processes are still running after all retries, restore the original crontab and exit with an error
echo "Error: PHP CLI processes are still running!"
crontab -u webapp .crontab
exit 1
test: "[ \"${INSTANCE_TYPE}\"x = \"workerx\" ]"
65_02_cronjob:
command: |
# Copy the environment-specific crontab file to the default crontab location
cp $CRONTAB app/config/crontabs/crontab.default
env:
# Define the path to the crontab file based on the current Elastic Beanstalk environment name
CRONTAB: "app/config/crontabs/crontab.`{ \"Ref\" : \"AWSEBEnvironmentName\" }`"
test: "[ -f $CRONTAB ]" # Run only if the specified crontab file exists
Config clound watch để quản lý log cho ứng dụng. Tạo file .ebextensions/03.cloundwatch.config
packages:
yum:
amazon-cloudwatch-agent: []
option_settings:
- namespace: aws:elasticbeanstalk:cloudwatch:logs
option_name: StreamLogs
value: true
- namespace: aws:elasticbeanstalk:cloudwatch:logs
option_name: DeleteOnTerminate
value: false
files:
"/etc/awslogs/awscli.conf" :
mode: "000600"
owner: root
group: root
content: |
[plugins]
cwlogs = cwlogs
[default]
region = ap-southeast-1
"/opt/aws/amazon-cloudwatch-agent/etc/cloudwatch.json" :
mode: "0644"
owner: root
group: root
content: |
{
"logs": {
"logs_collected": {
"files": {
"collect_list": [
{
"file_path": "/var/log/containers/nginx-proxy/access.log",
"auto_removal": true,
"log_group_name": "`{"Fn::Join":["-", [{ "Ref":"AWSEBEnvironmentName" }, "nginx"]]}`",
"log_stream_name": "{instance_id}_access.log"
},
{
"file_path": "/var/log/containers/nginx-proxy/error.log",
"auto_removal": true,
"log_group_name": "`{"Fn::Join":["-", [{ "Ref":"AWSEBEnvironmentName" }, "nginx"]]}`",
"log_stream_name": "{instance_id}_error.log"
},
{
"file_path": "/var/app/support/logs/**.log",
"auto_removal": true,
"log_group_name": "`{"Fn::Join":["-", [{ "Ref":"AWSEBEnvironmentName" }, "app"]]}`",
"log_stream_name": "{instance_id}_pm-app.log"
}
]
}
}
}
}
container_commands:
01:
command: "sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:/opt/aws/amazon-cloudwatch-agent/etc/cloudwatch.json"
02:
command: "sudo systemctl enable amazon-cloudwatch-agent.service"
03:
command: "sudo systemctl restart amazon-cloudwatch-agent"
Tài liệu tham khảo:
https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-Configuration-File-Details.html
Khi chạy xong ứng dụng chúng ta cần migrate database và set quyền cho thư mục code. Tạo file set permission .platform/hooks/postdeploy/01_set_permissions.sh
#!/usr/bin/env bash
for dir in \
/var/app/current/app/logs \
/var/app2/support/logs \
/var/app/current/app/tmp \
/var/log/eb-docker/containers/app
do
[ ! -d "$dir" ] && mkdir -p $dir
chmod -R 777 $dir
done
Tạo file migrate database .platform/hooks/postdeploy/02_migrations.sh
#!/usr/bin/env bash
docker ps
DOCKER_PHP_ID=`docker ps -q --filter 'ancestor=AWS_ACCOUNT_ID.dkr.ecr.AWS_DEFAULT_REGION.amazonaws.com/DOCKER_IMAGE_NAME:DOCKER_IMAGE_VERSION'`
echo "Docker id: $DOCKER_PHP_ID"
docker exec -i $DOCKER_PHP_ID chown -R www-data:www-data ./
docker exec -i $DOCKER_PHP_ID chmod -R 777 logs
docker exec -i $DOCKER_PHP_ID composer install --no-interaction --prefer-dist --optimize-autoloader
docker exec -i $DOCKER_PHP_ID bin/cake migrations migrate --no-lock
docker exec -i $DOCKER_PHP_ID bin/cake migrations migrate -p LoginAttempts --no-lock
docker exec -i $DOCKER_PHP_ID bin/cake migrations migrate -p Queue --no-lock
docker exec -i $DOCKER_PHP_ID bin/cake schema_cache clear
Tài liệu tham khảo:
https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/platforms-linux-extend.workflow.html