Deploying Laravel on AWS ECS

Yosi Pramajaya
6 min readAug 25, 2019

According to statistics, PHP is still the most popular server-side programming language used by almost 80% of the internet. Among PHP frameworks, Laravel is one of the most popular and widely used. Do you use Laravel in your production environment?

Forge and Envoyer can make it very easy for you to deploy them to one or more servers but it might get difficult when you need to scale automatically. By scaling, I mean scale-out when needed, and scale-in when not needed.

Note: While this tutorial is designed to deploy Laravel app in mind, you can use it for other containerised applications.

What is ECS?

Docker containerises our application and makes it easy for us to quickly and reliably run our application from one computing environment to another. But when we have so many containers, we need orchestration tool.

Amazon Elastic Container Service (ECS) is one of some popular container orchestration service. It allows us to run and scale our containerised applications on a cluster of EC2 instances.

Another alternative for AWS Cloud is EKS, Kubernetes-based orchestration service, that comes with additional cost.

Why ECS?

I like it because it’s very simple to deploy multi-container apps. We can configure what images to use, set memory-limit / CPU-limit, volumes, port, etc. Amazon ECS is also very scalable and can easily be integrated with other AWS services.

Let’s try to deploy a simple Laravel application to ECS. We will need:

  • Docker images of our Laravel app
  • ECS Cluster
  • EC2 Instance
  • Application Load Balancer
Simple architecture of our app. Source

Step 1. Prepare the images

Usually, the images that we need would be: app, nginx, and redis. I recommend running the database on RDS instead on EC2 instance.

Build the images and push to ECR. ECS can directly pull images from ECR without any configuration. This feature allows us to use pipeline to continuously deploy the latest image to ECS!

Step 2. Create Cluster

Amazon ECS has 2 launch types. Fargate and EC2 Instance. AWS Fargate is very cool because it allows us to run containers without thinking of server but it’s still pretty expensive. So let’s go with EC2-based cluster.

Cluster Templates in ECS

Cluster configuration is not complicated. We can set the name and VPC. We can create a new VPC or choose existing VPC.

Step 3. Write Task Definition

Task Definition is the configuration file that will be launched by ECS. The concept is very similar with docker-compose.yml. We can write Task Definition through ECS Dashboard or directly with JSON file.

Task Definition

It may seem overwhelming but let’s try to focus on the essentials:

  • Task Size
  • Volumes
  • Container Definitions

Task Size

Setting limit in ECS is required. But you can set here or in Container Definitions. Just make sure that there’s no conflict in the limit settings. For simplicity, I recommend to just set it in Task Size.

Volumes

We want to have a shared volume between our app and nginx containers.

Container Definitions

This is where we set up our containers with the prepared images. There’re 3 images we want to create:

  • app
    This is where you set up your Laravel configuration (usually found in .env file) through environment variables.
    Also you want to make sure the app container mount the shared volume we just created, with path: /var/www. Also we want to link app to redis.
  • nginx
    This is where we set up the nginx image. Configure both Host and Container port: 80. And also mount the shared volume, with the same path as app. We want to link nginx to app.
  • redis
    We only need to think of the port. Which we want to set up at app’s environment variables.

Task Definition is organised by version. We can always create a new version based from the previous one and make some modification.

Step 4. Running the Task

Now we can deploy our containerised applications by running the Task. Make sure you have a running ECS Cluster instance or launch a new one.

When the Task is RUNNING we can try to visit the IP of the instance to see if our application is deployed. If you encounter some problems, try this:

  • Make sure your ECS Cluster Instance have more memory/CPU than the limit set in Task Definition
  • Make sure the Security Group of your ECS Instance allows access for essential port. In this case, port 80.
  • If problem occur related to IAM Role or Permission, make sure your ecsTaskExecutionRole has correct permission.
  • If you’re using RDS, make sure database is running well and accept connections from your ECS Instances
  • ECS will automatically log errors to CloudWatch. You can check the logs for more detailed information.

Step 5. Create a Service

This is where ECS gets very useful. ECS Service will

  • Make sure your Task keep running. When it stop, it will create and launch a new Task.
  • Integrate with AWS Load-Balancer to distribute traffic across the Tasks.
  • Integrate with Auto-Scale policy to scale-out, and scale-in

To create a service, you need a working Task Definition. In the configuration you can define number of tasks you want to run, deployment type, network, load-balancer, and auto-scaling policy.

Configure Service

We can set the Task Definition that will be launched by the service. We should set the service name, number of tasks, deployments, and task placement, all which you can just go by default.

Configure Network

Here we can choose to set the VPC, Subnets, and Security Group.

We should set load-balancer for our service here. Application Load Balancer will distribute traffic to our ECS instances, this allows us to auto-scale our app.

Configure Auto-scaling

We can set auto-scaling policy for our Task. We can set the minimum, desired, and maximum number of tasks.

Automatic task scaling policy has 2 types:

  • Target tracking
  • Step-scaling

Target tracking policy would be much simpler to use. Step-scaling allows us to use CloudWatch alarm which can be very detailed.

This auto-scaling policy will only scale our running Task in EC2 instances. Therefore, we must make sure to also have auto-scale policy for our EC2 instances so that it can automatically launch new instance when needed. Or we can just use AWS Fargate and we don’t need to worry about any EC2 instances.

And that’s it! You have successfully deployed a Laravel application on Amazon ECS.

Some tips…

  • Clean Up: To save cost, make sure you shutdown everything related to ECS. This includes: services, task, instances, and load-balancer
  • Metrics: ECS provide a very useful CPU/Memory Utilisation metrics. Pay attention to how much you actually need to save more cost
  • Microservice: Lumen is a microservice framework by Laravel. You can deploy Lumen and use ECS Service Discovery + AWS App Mesh to manage your microservice application.

Thanks for reading! Feel free to share your opinion through comments.

--

--

Yosi Pramajaya

Tech Lead, Cloud Architect, Machine Learning Practicioner