Deploying a Symfony 4/5 Application on AWS Fargate (part 2)

Jérémy Levy
Jul 18 · 6 min read

Hello 👋,

In this series of articles, we learn how to create and deploy a production-ready application on .

In the first part, we have created a fully-working application with some controllers, some entities, some forms, some views, some tests, some assets and some migrations.

In this part, we will use create all the components required to deploy our application on (CI/CD, auto-scaling, load-balancing, SSL, CDN…).

provides us with a “catalog” of architectures that we could use to create a complete cloud architecture on your own , or account.

It also offers us additional features like deployment monitoring/rollback, environment variables management, CI on all branches, health monitoring, and so on.


Step 1 — Creating our architecture

Image for post
Image for post

To start using , go to https://getrevolv.com and click on the “Login with GitHub” button.

Once registered, click on “Create an architecture”. You will be redirected to the architectures “catalog”.

At the time of writing, the sole architecture available is a Docker-based architecture for HTTP projects.

It will fit perfectly well with our application, so we will use it.

Image for post
Image for post

Once selected, we need to choose the providers that we want to use. For our application it will be , and We also want aCDN for our assets:

Image for post
Image for post

Next, click on “Review my architecture” to review all the components that will be created on your account:

Image for post
Image for post

Once reviewed, click on “Configure my source provider”. You will be redirected to to install the application.

Once installed, choose the repository containing your application, then click on the “Configure my architecture” button.

Image for post
Image for post

In the final step, set the domain name that you want to use and make sure that the selected branch is the one which you want to deploy from:

Image for post
Image for post

Next, add the environment variables required by our application:

APP_ENV=prod
DATABASE_URL=${REVOLV_MYSQL_URI}
Image for post
Image for post

The “pre-deploy command” is a command that will run, as part of our CI, in a newly created production container, just before deployment.

At this stage, your application has been built and your tests have run, so it’s the perfect time to run your database migrations:

php bin/console doctrine:migrations:migrate --no-interaction
Image for post
Image for post

Next, click on the “Create this architecture” button. You will be asked to connect your AWS account.

Follow the instructions, then click on “Create this architecture”.

Image for post
Image for post

Congrats! 🎉

Step 2 — Setting up our domain name and HTTPS

Now that our architecture is created and our app is deploying we need to configure several things.

First, we want to set up our domain name and enable HTTPS.

To do this, go to the “Readme” section and add the displayed DNS records to your domain host:

Image for post
Image for post

[0] https://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html

[1] https://docs.aws.amazon.com/acm/latest/userguide/acm-overview.html

Step 3 — Running our tests on each build

After setting up our domain name and enabling HTTPS, we want to run our tests on each build.

For this, we need to customize the “Test” stage of our CI.

But first, given that we have functional tests that require a database, we need to add a DATABASE_URL environment variable to our build environment.

To do this, go to the “Configuration” section, then scroll to the CI/CD section.

Add the following environment variable and click on the “Update environment variables” button:

DATABASE_URL=${REVOLV_MYSQL_URI}_test

Once your architecture has been updated, go to the “Readme” section and download the buildspec.master.test.yml file to customize the “Test” stage of your CI.

Image for post
Image for post

Set it at the root of your repository and update it as follow:

# ./buildspec.master.test.yml# ...phases:
# ...
build:
commands:
- docker-compose -f docker-compose.ci.yml run app ./vendor/bin/simple-phpunit
# ...

For reference, our docker-compose.ci.yml contains the following code:

# ./docker-compose.ci.ymlversion: "3.7"services:
app:
build:
context: .
dockerfile: Dockerfile.dev
entrypoint: /entrypoint.test.sh
environment:
- APP_ENV=test
- DATABASE_URL
- COMPOSER_MEMORY_LIMIT=-1

The DATABASE_URL value will be taken from the shell.

[0] https://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html#build-spec-ref-syntax

Step 4 — A CDN for our assets

Your domain name is now configured, SSL is activated and your tests will run on each build. What could be missing?

The last step to be labelled “production-ready” is to use a CDN for our assets.

Using a CDN for our assets is a two-step process.

First, we need to update the urls generated by for our production environment.

To do this, we’ll update our webpack.config.js as follow:

// ./webpack.config.js// ...if (Encore.isProduction()) {
Encore.setPublicPath(process.env.CLOUDFRONT_URL + "/" + process.env.COMMIT_ID);
// guarantee that the keys in manifest.json are *still*
// prefixed with build/
// (e.g. "build/dashboard.js": "https://abcde.cloudfront.net/dashboard.js")
Encore.setManifestKeyPrefix('build/');
}
module.exports = Encore.getWebpackConfig();

The generated urls in our production environment will now look like this:

process.env.CLOUDFRONT_URL + "/" + process.env.COMMIT_ID + path

Given that our assets are built in our Dockerfile, we need to find a way to pass these environment variables to our image.

To do this, add the following instructions in your Dockerfile:

# ./Dockerfile# ...FROM base as assetsARG COMMIT_ID
ARG CLOUDFRONT_URL
ENV COMMIT_ID=$COMMIT_ID
ENV CLOUDFRONT_URL=$CLOUDFRONT_URL
# ...

Then, go to the “Readme” section and download the buildspec.master.yml file to customize the “Build” stage of your CI.

Set it at the root of your repository and update the docker build command as follow:

# ./buildspec.master.yml# ...phases:
# ...
build:
commands:
# ...
- docker build --build-arg COMMIT_ID=$CODEBUILD_RESOLVED_SOURCE_VERSION --build-arg CLOUDFRONT_URL=$REVOLV_ASSETS_CLOUDFRONT_URL -t $REVOLV_REPOSITORY_URI:latest -t $REVOLV_REPOSITORY_URI:$IMAGE_TAG .

# ...
# ...

Finally, we need to upload our assets to our bucket.

To do this, go to the “Readme” section and download the buildspec.master.predeploy.yml file to customize the “Pre-deploy” stage of your CI.

Set it at the root of your repository and open it. An example has been added in the post_build section.

As you have seen, uploading your assets to S3 is a four-step process. Let’s implement it now:

# ./buildspec.master.predeploy.yml# ...phases:
# ...

post_build:
commands:
- $(aws ecr get-login --region $AWS_DEFAULT_REGION --no-include-email)
- id=$(docker create $REVOLV_REPOSITORY_URI)
- docker cp $id:/symfony/public/build ./build
- aws s3 sync ./build s3://$REVOLV_ASSETS_S3_BUCKET/$CODEBUILD_RESOLVED_SOURCE_VERSION --cache-control max-age=31536000,public

[0] https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/DownloadDistS3AndCustomOrigins.html

[1] https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Introduction.html

[2] https://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html#build-spec-ref-syntax

Conclusion

That’s it! Push all of these files and you’re set! 🎉

Your tests will run, your migrations will be executed and your assets will be uploaded.

Image for post
Image for post
Image for post
Image for post

You have deployed a application on a docker-based architecture with CI/CD, auto-scaling, zero downtime deployment, SSL, load-balancing, high availability, a CDN and a database. All of this on your own AWS account.

If you don’t plan to use this architecture you can destroy it to avoid being charged for the resources created on your AWS account:

Image for post
Image for post

Love 🖤

The Revolv blog

We help every person on the planet accelerate the deployment of world-changing projects.

Jérémy Levy

Written by

Building @getrevolv to automate cloud architecture creation.

The Revolv blog

From startups to NGOs, our mission is to help every person on the planet accelerate the deployment of world-changing projects.

Jérémy Levy

Written by

Building @getrevolv to automate cloud architecture creation.

The Revolv blog

From startups to NGOs, our mission is to help every person on the planet accelerate the deployment of world-changing projects.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store