Welcome to the transformative world of Docker! In this comprehensive and hands-on guide, we will unlock the full potential of Docker for your business by walking you through the installation, setup, and deployment of a React and Node.js full-stack application on an AWS EC2 instance.
In Part 1, we begin with a seamless installation of Docker on an EC2 instance, guiding you through the essential security configurations.
In Part 2, we retrieve our application code from a GitHub repository, showcasing a dynamic React frontend and a robust Node.js backend.
Part 3 is the heart of our journey. Here we delve into the intricacies of crafting Dockerfiles for both applications, setting the stage for containerization.
With the groundwork laid, in Part 4, we demonstrate the process of building, authenticating, and pushing our Docker images to the Docker Hub, providing a centralized repository for seamless collaboration. We learn how to pull these images into different machines effortlessly, ensuring consistency across your development environment.
In Part 5, we introduce the essential skills of managing Docker containers, from starting and stopping to exploring the realm of Docker Compose.
Brace yourself for an immersive experience, where each step is a leap towards mastering Docker and empowering your business with containerized applications.
Let’s roll up our sleeves and dive in!
Part 1: Installing Docker in EC2
- Spin up a free EC2 AWS instance and start an EC2 instance.
- Login to the AWS console. Select the EC2 instance -> Click on the security tab -> Click on the Security Group link as shown in Figure 1.
- Click on Edit Inbound Rules, as shown in Figure 2.
- Make sure you have all the rules as shown in Figure 3.
- Login using putty into the EC2 instance and run the below commands.
- Let’s install Docker using the below commands.
- sudo yum update
- sudo yum install Docker
- To make sure Docker is installed, try the below command to see the version of Docker.
- Sudo docker version
Part 2: Getting the application code
- I have created two sample programs on Github.
- Frontend application using Vite and React, which we will try to deploy using Docker (react_app folder): It shows simple text and a loading message while it makes an API call, and after receiving a response from the Node app, it shows it.
- Backend nodeJS application (node_app folder): Simple GET method that returns a text
- Here is the GitHub link:https://github.com/mahalingam-iyer/dockertraining
- Let’s clone the project inside a folder in EC2 and try to build and deploy
- You will have two folders, node_app and react_app.
Part 3: Writing DockerFile
- Write a DockerFile for react_app with the name Dockerfile.prod.
- Write a DockerFile for node_app with the name Dockerfile.prod.
Part 4: Building and Running Containers
- Now that we have Dockerfile, which is a set of instructions to create an image that will be used to create a container that is actually running our application,
- Before we start, go into the react_app folder and open the app. js using
- Vi app.js
- Change the IP address on the line where we make the fetch API call to the correct public address of your EC2 instance.
- At this point, we need to authenticate Docker.
- Create a new account (if not already done) on Docker Hub:https://hub.docker.com/Docker Hub is a repository for us to store our images, which can be pulled and spined just like our github.com holding code. Docker Hub holds images.
- Create two new repositories with nodes where we will store our images.
-
Once you have an account, hit the command in EC2.
- Docker login
- Enter a username and password.
- Now, from our code, we will create an image for the React app.
-
React_app (folder) type below the command
- In Docker Hub, whatever your username is, replace it in the below command, and since I have named the repository React, I am saying React:1.0.0 as it’s the first version.
- sudo docker build -t <user_ name>/react:1.0.0 -f./Dockerfile.prod.
- The dockerbuild command is used to generate an image from our code with the instructions mentioned in the Dockerfile. prod we created in previous step, and we are saying run it in current directory using ‘.’
-
- Now, from our code, we will create an image for the Node app.
- Node_app (folder) type below the command
- In Docker Hub, whatever your username is, replace it in the below command, and since I have named the repository a node, I am saying node:1.0.0 as it’s the first version.
- sudo docker build -t <user_ name>/node:1.0.0 -f./Dockerfile.prod.
- The dockerbuild command is used to generate an image from our code with the instructions mentioned in the Dockerfile. prod we created in the previous step, and we are saying run it in the current directory using ‘.’
- Pushing to Docker Hub
- Now we have created images in our local machine, but other machines can’t access them; hence, we will push the image to a remote repository, i.e., Docker Hub.
- You can check the created images using the sudo docker images command, which will list all available images.
- sudo docker push <user_name>/react:1.0.0
- sudo docker push <user_name>/node:1.0.0
- Now you can visit Docker Hub in your browser and see our image there.
- Pulling images from a different machine
- Suppose you want to run the image on another computer.
- You will have to login to Docker from the command line.
- We will have to first pull the image and then run it like we do with our code on Github.
- sudo docker pull <user_name>/react:1.0.0
- sudo docker pull <user_name>/node:1.0.0
- Check in this new machine using sudo docker images; it will list the two images.
- Running a container from the image
- -d is used to run the app in the background so our command prompt is not blocked. This flag stands for "detached" or "daemon" mode. It means the container will run in the background, and you'll get your command prompt back for further use.
- The nextpart specifies the Docker image to run. It includes the image name and its tag:
- <user_name>: This should be replaced with the actual Docker Hub username or registry where the Docker image is hosted.
- react: This is the name of the Docker image.
- 1.0.0: This is the tag of the Docker image, indicating a specific version. The tag allows you to choose a particular version or variant of the image. In this case, it's version 1.0.0.
- -p 80:80: This part specifies port mapping for the container. It tells Docker to map port 80 on the host to port 80 in the container. Here's what each part means:
- -p: This flag is used to define port mappings.
- 80:80: This indicates the port mapping. It means that incoming traffic on port 80 of the host will be directed to port 80 inside the container.
- sudo docker run -d -p 80:80 <user_name>/react:1.0.0
- sudo docker run -d -p 3000:3000 <user_name>/node:1.0.0
So, when you run this command, Docker will pull the specified image (if it's not already available locally), create a container based on the image, and run it in detached mode. The container will be running the React application (version 1.0.0) and be accessible on port 80 of your host system. The -p flag allows you to expose the container's port 80 to the host's port 80, so you can access the application by visiting http://localhost or from another computer by hitting http://<public_IP of EC2> in the web browser.
This React application will talk to the Node app and fetch data.
Part 5: Stop the container
- If we are done and want to stop the container
- Let's first list our containers, then stop and remove them.
- Sudo Docker PS (only running containers listed)
- Sudo docker ps -a (all containers)
- Copy the container ID that you want to stop
- Sudo docker stop <container_id>
- You can start it again by replacing stop with start in the above command.
- Sudo docker rm <container_id>
Part 5: Running using Docker Composer
- In the previous step, we deployed the frontend and backend separately; now we will combine both and do it as a single application using Docker Compose.
- Let's install Docker Composer.
- sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname-s)-$(uname -m)" -o /usr/local/bin/docker-compose
- sudo chmod +x /usr/local/bin/docker-compose
- Create a new file, docker-compose.yml.
- Add the below content.
- docker-compose up -d
Wonder why we have 1.0.8? I have changed the code over a period of time and built it.
Each time I updated my code into github, I built it using the docker build and ran it using the docker run command.
For a more in-depth introduction to Docker, we recommend visiting Blog : Role of Docker in Optimizing JavaScript Full-Stack Applications where you can explore fundamental concepts and benefits of Docker technology.