So now the cluster and the service we started
in ECS was deleted, now we can create a new cluster,
new tasks, new services to run our backend container here.
So for that I'll use this UI, click on Create Cluster
and then choose a Networking only cluster here.
Click Next step, give this cluster a name of your choice,
I'll name it goals-app but this name is totally up to you.
Check Create VPC and keep all the defaults here,
this ensures that AWS sets up private cloud
for this cluster, for all of the containers in the cluster
and click Create.
Now this will create this cluster
and the cluster is just the surrounding network
for your containers thereafter.
So let's wait for this cluster creation to finish,
and this can take a couple of minutes.
Once this finished click on View Cluster
and now we need to add tasks and services here.
Now services are based on tasks
so we need to create a task first.
And we do this under Task Definitions.
Now I already got two task definitions here,
we are going to create a new one though.
So create a new task definition and choose Fargate here
to have this serverless container execution environment
where your containers can scale infinitely
and you only pay for what you need.
Click on Next step and give this task definition name
and I'll name it goals.
On task role you should have
a ECS task execution role available,
make sure you choose that one.
If you don't have that, you should delete the entire cluster
again and launch at first run wizard again and go through
that instead because this will then create this role.
Scroll down and choose the smallest sizes here
for the memory and CPU to keep costs down.
Of course for real apps you might wanna choose
more powerful settings here to speed up your code execution,
it depends on the app you're building and it will take time
and experience to find out what you need here.
And then on container definitions click on Add container.
Here give your a container a name
and I'll name it goals-node because that will be the backend
or maybe therefore name it goals-backend container.
And then use this repository here,
this image name academind/goals-node in my case.
On Port mappings make sure you map port 80
because that is the port exposed by this application,
we're listening on port 80 here in our node JS code.
Ignore the health check but here under environment,
I now do wanna change something.
It is worth pointing out that
in hour docker file for this backend image,
we are actually executing npm start here as a final command.
And that in turn will then utilize nodemon
to start app js.
Now I used nodemon locally to have this life reloading
when we change something in our code.
Now in production we won't have that,
we also won't have to bind mounts to feed any live code
into the running app,
I talked about this early already, why we don't do that.
So therefore we of course don't wanna use nodemon
to execute our code here, we wanna use node.
So therefore here on command I'll enter node app js.
There should be a comma separated list here,
cd hint here if nothing was entered
and they offer node, app js will execute the app js file
inside of the container with the node runtime.
And that is a change we should make here
and that also shows us how we again can leverage the exact
same image and container during development and production
and still find tune individual aspects
to the different environments where we run the container,
which is not a problem but actually a feature of docker.
We still have the locked in code and delocked in runtime.
We use node here, that's locked into the image.
So we have that guarantee of having the same application
and application environment in development and production,
that main asset docker is all about.
And still we can find tune individual aspects
that need fine tuning like here
where we use npm start locally
and use node app js in production.
Now we should specify the environment variables.
And here I just noticed something,
in the docker file we should of course
also add this new environment variable,
MONGODB URL environment variable which we're using
in the MONGODB connection string now.
So make sure you add this ENV definition
in your docker file and then actually rebuild
that docker file by running the docker build command again.
And then of course also tag it again
to the academind/goals-node image name in my case.
So to that docker hub repository image,
and then push updated image to ensure
that your docker file lists all the environment variables
which are getting used inside of the container of code.
Now with that, back on AMS ECS we now can specify
the environment variables here.
And that's another important thing, locally
when we run our container locally we use docker compose
to run these multiple containers,
and there we then of course used the env file configuration
to point at an env file.
Alternatively if we use to docker run command,
there we also add an option for adding environment variables
or pointing at an environment variable file.
Here it was the env, the --env file option.
Now we don't have an environment file here
when we use AWS ECS but we can add our environment variables
as key value pairs here.
So therefore I now will go into the backend env file
and grab the environment variables here
and add them as keys.
So MONGODB username, MONGODB password and MONGODB URL
and then add values here.
And I will use the same values as I did during development
though in reality you might wanna consider choosing
more complex usernames and passwords
but I will go with these ones.
But I will change my URL,
I used MONGODB here in development because there thanks
to docker compose and this network being created
by docker which was a very useful feature here locally.
We could use the container name as an address
for requests being made from one container
to another container.
AWS ECS doesn't support this feature like this,
but it does have another neat feature
which is easy to set up and use.
When we add multiple containers to the same task
which we are going to do,
we are going to add the MONGODB container
to this same task as this container is part of,
then these containers can communicate
with each other under the local host key.
So it basically emulates a local system
where all containers are on the same host you could say.
So here in production, in AWS ECS we can use local host
to send the request to some other container
which will be part of the same task.
And therefore I use local host as a value for MONGODB URL
in production, we use MONGODB as a value in development
because in development local hosts wouldn't work.
So that's again another difference
but again we are implementing this such
that our application code is not effected.
There we just use an environment variable
for getting the real address and then the value
for that address depends simply
on where we run this container, and that again ensures
that what's in the container is locked in
and works equally in all environments.
And then we may just choose to run things differently
in different environments.
So with that, I added these free environment variables.
We don't need to set up anything else here
in the other parts.
We also don't need to set up anything for storage
and log in because the two volumes I did set up
for my backend here, I removed the logs which we used
in docker compose and therefore the two remaining volumes
we have here are really just a bind mount
and then an anonymous volume to ensure
that the bind mount doesn't overwrite node modules.
Since we're not using bind mounts in production,
we therefore don't need to add any volume at all here.
So therefore we can now click Add
and with that we added our first container here.
But of course that's not the only container we want here,
after all we have an application
that uses two containers here, the backend and MONGODB.
So let's now add MONGODB as well.