Overview of Creating and Deploying a Multi-Container Docker Application to AWS
by John Vincent
Posted on June 7, 2021
Let's discuss deploying TaskMuncher, a React and Node application, to a Multi-Container Docker Environment at AWS using Dockerhub and Travis CI
For extensive discussions regarding TaskMuncher, please see TaskMuncher Overview
Overview
It is apparent that this is an extremely difficult process with so many complex steps each requiring exact configuration. Further, each technology places its own architectural requirements upon the technologies around it so the architecture of the whole solution is extremely precise and devoid of options.
In software development it is often customary to architect and build from software to deployment. It is thus assumed the deployment process could be sufficiently customized to be able to handle any and all problems that appear as part of the deployment process.
My experience of these technologies is that this is a hazardous resolve. This approach allows for the resolution of architectural issues with a technology only to find architectural issues in the next technology that would cause a return to the drawing board and a considerable amount of rework.
Thus, for this topic, I have described the steps in what would appear to be reverse order. It is not customary but I believe this approach will allow for a better comprehension.
-
Configuring the Deployment Environment of AWS, Dockerhub and Travis-CI
-
Allow AWS to authenticate with a Dockerhub private repository
-
Configure Travis-CI for Docker Multi-container Deployment to AWS
Configuring the Deployment Environment of AWS, Dockerhub and Travis-CI
The following illustrates the dependencies of the various components.
To configure the above there are a series of tasks. They must be performed in the order shown.
So let's recap.
-
AWS Elastic Beanstalk Application requires the use of a
Docker platform
and must useMulti-Container Docker running on 64bit Amazon Linux
. -
Elastic Beanstalk doesn't know how to run containers and so it hands it off to
Amazon Elastic Container Service (ECS)
. -
ECS uses
Dockerrun.aws.json
, a task definition to run each container. -
The multi-container Docker platform on Elastic Beanstalk does not support the building of custom Docker images during deployment. Thus custom Docker images are stored in a private Dockerhub repository.
-
AWS needs a
.dockercfg
file to uploaded to S3 bucket to allow AWS to authenticate with a Dockerhub private repository. -
Dockerrun.aws.json
requires configuration so it can access the.dockercfg
file in the S3 bucket. -
Travis needs to be configured with the AWS Access Keys allowing for access to AWS.
-
Travis needs to be configured with the Dockerhub id and password so it can push the custom images to a Dockerhub private repository.
-
To perform a build and deploy, Travis requires a
.travis.yml
file with specific instructions.
Thus it is clear there are a series of cascading requirements that dictates the terms of software development. There is more.
-
Deploying to AWS Beanstalk Multi-Container environment implies the existence of a single deployment thread, that being a single
.travis.yml
. -
This suggests there is only one Github repository.
-
Running Docker requires a context of the current directory or a subdirectory of the directory in which Docker is running.
-
This requires the source code of the components of the application to be subdirectories of the Docker working directory.
Thus the deployment environment and processes dictate to software development that there shall be one and only one Github repository. This is clearly problematic.
It is necessary to first carefully determine the deployment architecture and then work backwards to determine how to architect the source code to allow for that deployment architecture.
Install Docker
For details, please see Install Docker and review Docker Basics
TaskMuncher AWS Production Docker Containers
Note
- Each of these components is a Docker Container.
- Requests are routed to Nginx server listening on port 80.
- Requests are proxied based on the URL of the request.
- Production React are just static files. They need to be served by another Nginx server which is listening on port 8100.
- Requests for APIs are routed to a Node/Express Server listening on port 3100.
- Requests for MongoDB access are routed to a MongoDB Container which is listening on port 27017.
- MongoClient Container seeds the database with the necessary startup data.
AWS offers an excellent MongoDB service. However, for this project I decided to deliver MongoDB as its own container.
TaskMuncher Development Docker Containers
TaskMuncher Production in Development Docker Containers
Developer Requirements
In summary, the required docker images are
client
server
mongodb
nginx
mongo-client
for each of the following environments
- development
- production in a development environment
- production at AWS
and also
dockercfg
in a development environment. See Allow AWS to authenticate with a Dockerhub private repository for details.
Configuring the Docker Environment
Now
- it is known what needs to be built
- how it is to be configured
- and what network configuration is required
This causes the requirement for the source code to be structured in a certain way.
I have chosen the following folder structure.
Configuring the Build Processes
The build requirements are so complicated a build system is a requirement.
I have chosen to use Makefiles. For details, please see Configuring Makefiles to build and run Docker Images using Docker, Docker Compose and Dockerfile
It is important to note that the Makefiles use Docker, Dockerfiles and Docker Compose to perform the various required tasks.
Notice that the builds use either
- docker
- docker-compose
Notice how the *-compose.mk
Makefiles are really just simple patterns to
- build
- start and attach to containers for a service
- stop containers, networks, volumes, and images created by up.
which, in the end, rely on a Dockerfile to 'configure' the image.
Notice how the build
directives in dev.mk
and devprod.mk
also rely on Dockerfiles.
Dockerfiles
docker-compose.yml
files are used for defining and running multi-container Docker applications.
Dockerfiles are simple text files that contain the commands to assemble an image that will be used to deploy containers.
The structure of the ./config
folder is as follows.
The ./config
folder shows a number of Dockerfiles.
The configuration of these Dockerfiles is discussed in Configuring Dockerfiles to build Docker Images.
Docker Development Environment
For details, please follow Creating and running a Docker Development Environment
Configuring and Using .env files
The multitude of requirements create the requirement there be many .env
files. This requirement creates some challenges.
For details, please follow Configuring and Using .env files
Delete AWS Resources
At completion of the project it is desirable to delete any and all resources that were used for this project. For details, please see Delete all TaskMuncher AWS Resources
Configuration Values
The following are listed here for the sake of simplicity and to remove duplication. I consider it to be a good practice to put all configuration information in one place.
Please note that all of the below were deleted before this document was published.
-
Default VPC
vpc-0dc1a7ee0c7bec811
-
Application:
taskmuncher-docker
-
Environment:
Taskmuncherdocker-env
-
Github repository:
taskmuncher
-
Workspace:
/Users/jv/Desktop/MyDevelopment/github/website/taskmuncher
-
Diagrams:
/Users/jv/Desktop/MyDevelopment/github/website/taskmuncher/diagrams
-
S3 folder:
taskmuncher-docker
-
S3 bucket name:
elasticbeanstalk-us-east-1-971716655829
-
AWS user:
taskmuncher-deployer
-
AWS_ACCESS_KEY:
-
AWS_SECRET_KEY:
-
AWS application url:
http://taskmuncherdocker-env.eba-mv2hwnxx.us-east-1.elasticbeanstalk.com/
-
Dockerhub repository:
johnvincentio/taskmuncher
References
AWS
-
Using the Multi-container Docker platform (Amazon Linux AMI)
-
Docker configuration on Amazon Linux AMI (preceding Amazon Linux 2)
-
Deploying Elastic Beanstalk applications from Docker containers
-
Multi-container Docker environments with the Elastic Beanstalk console
Docker
- Docker Login
- Docker Docs
- Repositories
- Quick start
- Docker run reference
- Docker Labs
- Docker Desktop
- Docker Desktop for Mac