Deploy WordPress On ECS Fargate Using CICD

This post shows you how to run WordPress without servers using Amazon ECS on AWS Fargate. We will create a VPC and an ECS cluster in which our WordPress tasks will run. An RDS MySQL instance will provide the database that WordPress requires.

Prerequisites

  • Dockerfile for Nginx

  • Dockerfile for PHP

  • AWS VPC

  • AWS CodeCommit

  • AWS CodeBuild

  • AWS CodePipeline

  • AWS ECR

  • AWS ECS

  • AWS CloudMap

VPC

Create a new vpc for your ECS project, must enable DNS Hostname & DNS Resolution.

Go to aws console search VPC - - - > Create a vpc

Name : ecs-vpc

IPv4 CIDR : 10.0.0.0/16

Select your newly created VPC - - - > goto action & enable DNS Hostnames & DNS Resolutions.

By the way, DNS Resolution is enabled by default.

Enable it - - - > then click on save changes button

Now create two public subnets - - - eg

Name : PublicSubnet-1a

CICR : 10.0.0.0/24

Name : PublicSubnet-2b

CICR : 10.0.1.0/24

Click on create subnet - - - > select your newly created vpc - - - >select ecs-vpc

Now create a Internet Gateway for your VPC

After creating an internet gateway - - - > you got a pop-up notification clickon that, it's asking you to attach your vpc from your internet gateway.

Click to : Attach to a VPC

Select your newly created vpc then click on Attach internet gateway button.

Now go to the Route Table, you do not create extra RT when we are creating a vpc it will automatically create a route table, you can see your vpc name so click on that.

Click on Edit routes - - - > then click on Add route.

0.0.0.0/0 that mean it will match to any IP address - - - > select Internet Gateway

Done!

RDS

Now goto ECS, for now create ecs deployment base infrastructure using php & nginx image, after successfully deployment we will test using CICD Pipeline,

Create a ECS Cluster - - - > click on Create Cluster

Elastic Container Service

Select cluster template : Networking Only

Now Configure Cluster :

Enable (mark on) CloudWatch Container Insights

After creating Cluster, move on to Task Definition - - - >

Click on Create new Task Definition - - - > select launch type Fargate - - - > Click on next step.

Select Launch Type : FARGATE

Task definition name : wp-php-td

Task role : ecsTaskExecutionRole

Network mode : awsvpc

OS Family : Linux

Task Execution Role : ecsTaskExecutionRole

Task Memory : 2GB

Task CPU (vCPU) : 1 vCPU

Now go to your workspace, create Dockerfile & other files for both nginx & php then push them into ECR Elastic Container Service.

Create a folder sudo mkdir wp-cicd

Create three folder under wp-cicd

  • mkdir php

  • mkdir nginx

Go inside the php folder, then create & download following files

  • Dockerfile : user could call on the command line to assemble an image

  • buildpsecfile : CodeBuild uses to run a build

  • test.html : change in this file (nothing but just Pipeline testing)

  • Index.php :

We have to download WordPress in the php directory for our Dockerfile.

Download WordPress & extract using linux command & after extracting wordpress file delete latest.tar.gz file

Dockerfile (php)

FROM php:7.2-fpm-stretch

COPY index.php /usr/share/nginx/html/

COPY ./wordpress /usr/share/nginx/html/

RUN apt-get update -y

RUN docker-php-ext-install mysqli pdo pdo_mysql && docker-php-ext-enable pdo_mysql

RUN apt-get install -y libcurl4-openssl-dev ssh nano pkg-config libssl-dev

index.php

<?php

phpinfo();

?>

revisiont.html

Deploying wordpress using cicd

ECR : Elastic Container Registry

Create a repository name : wp-php

Retrieve an authentication token and authenticate your Docker client to your registry

aws ecr get-login-password --region us-east-2 | docker login --username AWS --password-stdin 660645611558.dkr.ecr.us-east-2.amazonaws.com

Build your Docker image using the following command

docker build -t wp-php .

After the build is completed, tag your image so you can push the image to this repository:

docker tag wp-php:latest 660645611558.dkr.ecr.us-east-2.amazonaws.com/wp-php:latest

Run the following command to push this image to your newly created AWS repository:

docker push 660645611558.dkr.ecr.us-east-2.amazonaws.com/wp-php:latest

Goto php directory & follow these commands.

Copy the URI of the php-image - - - > goto ECS - - - > Add container - - - >

Container Name : php-container
Image : copy the URI from ECR of wp-php
Port : 9000

Environment variables | RDS | php-container

AWS_RDS_HOSTNAME : database-1.cvafffm3a4pp.us-east-2.rds.amazonaws.com

AWS_RDS_DB_NAME : wpdb

AWS_RDS_PASSWORD : password

AWS_RDS_PORT : 3306

AWS_RDS_USERNAME : admin

Click on view task definition - - - > Click on Cluster - - -> Click on Cluster

Create service for php ‘Backend’

Select launch type : fargate

Task Definition : wp-php-td

Cluster : ECS-Fargate

Service Name : php-srv

Number Of Task : 1

Remember previously we created vpc & subnet, select that resources.

Enable service discovery.

Namespace : local

Service discovery name : php

AWS Cloud Map

AWS Cloud Map is a cloud resource discovery service. With Cloud Map, you can define custom names for your application resources, and it maintains the updated location of these dynamically changing resources

Go to cloud map - - - > a namespace created there

Php part is completed from this ECS side!

Now go to Nginx directory and create some file

  • Dockerfile

  • buildspec.yml

  • nginx.conf

  • index.php

  • test.html

  • wordpress/

Dockerfile

FROM nginx:mainline

RUN rm -rf /etc/nginx/conf.d/*

COPY ng.conf /etc/nginx/conf.d/

COPY index.php /usr/share/nginx/html/

COPY test.html /usr/share/nginx/html/

nginx.conf

server {

listen 80;

server_name _;

root /usr/share/nginx/html;

index index.php index.html;

add_header 'Access-Control-Allow-Origin' '*';

add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, Accept, Origin, Response-Type';

add_header 'Access-Control-Allow-Methods' 'GET,PUT,POST,DELETE';

access_log /var/log/nginx/access.log;

error_log /var/log/nginx/error.log;

#location / {

try_files $uri /index.php$is_args$args;

#}

try_files $uri $uri/ @rewrite;

location @rewrite {

rewrite ^/(.*)$ /index.php?_url=/$1 ;

}

location ~ \.php$ {

try_files $uri =404;

include fastcgi_params;

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

fastcgi_pass php.local:9000;

}

}

“Must (In the loopback ip paste the Cloud Map namespace php.local along with php port 9000)

This will connect with the php container, in the loopback IP

index.php

<?php

phpinfo();

?>

test.html

Deploying wordpress using CICD

Now we have to download wordpress for nginx.

sudo wget -c http://wordpress.org/latest.tar.gz

sudo tar -xzvf latest.tar.gz

Download WordPress & extract using linux command & after extracting wordpress file delete latest.tar.gz file

sudo rm -rf latest.tar.gz

Now goto ECR created a new repository for nginx.

ECR

Now goto terminal go inside of nginx directory & then follow all these steps.

Build your Docker image using the following command

docker build -t wp-nginx .

After the build is completed, tag your image so you can push the image to this repository:

docker tag nginx:latest 660645611558.dkr.ecr.us-east-2.amazonaws.com/wp-nginx:latest

Run the following command to push this image to your newly created AWS repository:

docker push 660645611558.dkr.ecr.us-east-2.amazonaws.com/wp-nginx:latest

Go back to your ECS Cluster, - - - > create a Task Definition - - ->

Select launch type Fargate

Task definition Name : wp-nginx-td

Task Role : ecsTaskExecutionRole

Network Mode : awsvpc

OS Family : Linux

Task Execution Role : ecsTaskExecutionRole

Task memory : 2GB

Task CPU (vCPU) : 1 vCPU

Click on Add container, copy the nginx image uri from ECR.

Environment variables | RDS | php-container

AWS_RDS_HOSTNAME : database-1.cvafffm3a4pp.us-east-2.rds.amazonaws.com

AWS_RDS_DB_NAME : wpdb

AWS_RDS_PASSWORD : password

AWS_RDS_PORT : 3306

AWS_RDS_USERNAME : admin

Click on View task definition - - - > Click on cluster - - - > click on create

Create a service : nginx

Launch type : fargate

OS family : Linux

Task Definition (family) :wp-nginx-td

Cluster : ECS-Fargate

Service Name : nginx-srv

Number Of Task : 1

Now select your vpc & subnets, security group & enable service discovery.

Select the existing Security Group that we created for both nginx & php.

Enable service discovery

Note :

  • Attach source of nginx | php security group in RDS inbound.

Check health both nginx & php service in Cloud Map

All good! Now go to nginx service - - -> click on task - - - > scroll down - - -

Take the public IP of nginx & hit on the web.

Note :

  • Change the wp-config-sample.php to wp-config.php

  • Edit the database and enter the same credentials as RDS.

  • Again build Dockerfile & push the image to ECR.

  • ECS : stop both services nginx, php it will automatically start with new revision.

test.html

Automate this process using CICD & IAM Policy

  • CodeCommit

  • CodeBuild

  • CodePipeline

Now goto IAM console - - - > Click on users - - - > Click on your username

Click on security credentials - - - > Scroll Down - - - > Come to the HTTPS section - - - > Click on Generate credentials - - - > Download the credentials.

HTTPS Git

Git credentials, an IAM-generated username and password pair you can use to communicate with CodeCommit repositories over HTTPS, perform all tasks eg : git pull, push etc.

Now take the https link to clone the nginx-repo from CodeCommit to your local environment.

IAM

Create two repositories for storing both nginx, php source code.

wp-nginx

Goto AWS console search CodeCommit - - - > create a repository for nginx.

Create a buildspec file for nginx CodeBuild, that will build our source code for deployment stage.

version: 0.2

phases:

install:

runtime-versions:

nodejs: 16

pre_build:

commands:

  • echo Logging in to Amazon ECR.....

  • aws --version

  • aws ecr get-login-password --region eu-west-2 | docker login --username AWS --password-stdin 660645611558.dkr.ecr.eu-west-2.amazonaws.com

  • REPOSITORY_URI=660645611558.dkr.ecr.eu-west-2.amazonaws.co..

  • IMAGE_TAG=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)

    build:

    commands:

  • echo Build started on date

  • echo Building the Docker image...

  • docker build -t $REPOSITORY_URI:$IMAGE_TAG .

    post_build:

    commands:

  • echo Build completed on date

  • echo Pushing the Docker images...

  • docker push $REPOSITORY_URI:$IMAGE_TAG

  • echo Writing image definitions file...

  • printf '[{"name":"nginx-container","imageUri":"%s"}]' $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json

artifacts:

files: imagedefinitions.json

  • Change something like aws region, aws account, image name without tag, container-name same as ecs.

  • Imagedefinition.json : magedefinitions. json file for Amazon ECS standard deployment actions. An image definitions document is a JSON file that describes your Amazon ECS container name and the image and tag.

wp-nginx

Now create the remaining ones php-repo - - - > click on create repository.

CodeBuild

Breathe build for both nginx & php after that we automate the build process using CodePipeline

wp-nginx-build

Buildspec : leave it as default it will take this buildspec.yml file from CodeCommit repository. If you want to directly write that file you do not need to upload on git, you can directly write your buildspec file in Insert build commands.

Now create build for php

AWS CodePipeline

Pipeline Succeeded

Now create another Pipeline for Php

Go to Pipeline console - - - > Edit - - - > Source - - - > Add stage - - - >

Click on Add action - - - > Source - - - > Edit the action.

For php Source & Build :

  • Source : SourceArtifact1

  • Build : BuildArtifact1

Php : Pipeline Editing completed.

Now do some change in any directory content from local (terminal)

Then push it to the CodeCommit Repository.

  • v2

Pipeline Succeeded

Take public IP & check new revisions.

Done!