Docker in Action 🤺- From Absolute Basics

Docker in Action 🤺- From Absolute Basics

Well, I am a big believer that learning Docker through projects is highly effective because it allows you to apply concepts in real-world scenarios, solidifying your understanding. Starting with the basics and progressing to advanced projects helps build a strong foundation while gradually exposing you to more complex challenges, enhancing your skills incrementally. It mirrors actual workflows, fosters problem-solving abilities, and ensures you're ready to handle real-world deployments.

In this blog, we will be going through a journey of building Docker projects from absolute basics and gradually progressing towards advanced projects. Stay tuned and let’s get started.

P.S - You will get all the source code on my GitHub Repository: https://github.com/nsahil992/Docker-Projects


  1. Project 1: Static Website Deployment (HTML, CSS, JavaScript)

    Problem Statement:
    To deploy a simple static website with HTML, CSS, and JavaScript files. We have to containerize this website using Docker and serve it through an NGINX web server. The website should be accessible on port 8080 of the host machine.

    Solution:

# We have to use official image of nginx as base image

FROM nginx:latest

# We have to copy the files into the container

COPY . /usr/share/nginx/html
  • FROM nginx:latest - This specifies the base image that we are using official nginx image. The :latest tag ensures we pull the most recent version.

  • COPY . /usr/share/nginx/html - The source (.) is the current directory (where index.html and styles.css are located). The destination (/usr/share/nginx/html) is the directory where NGINX serves files from by default.

docker build -t static-website .
  • -t static-website: Tags the image with the name static-website.

  • .: Specifies the build context (current directory).

docker run -d -p 8000:80 static-website
  • -d: Runs the container in detached mode (in the background).

  • -p 8000:80: Maps port 80 inside the container to port 8000 on our host machine.

Push the image on our Docker Hub:

# To push the image to our Docker Hub, we have to first tag the image with our username

docker tag static_website yourusername/static_website:latest

# Finally, pushing the image to Docker Hub

docker push nsahil992/static_website:latest

Problems I encountered:

  • Port Mapping Issue:

    docker run -d -p 8000:8000 static_website

    I have mistakenly mapped host port 8000 to container port 8000, whereas, nginx listens to port 80 and not 8000.

How I solved it:

  • Corrected the command: docker run -d -p 8080:80 static_website

  1. GO REST API :

    Problem Statement:

    In this project, our goal is to create a simple REST API using the Go (Golang) programming language and containerizing the application with Docker.

    Solution:

# Using official image of Go as the base image

FROM golang:1.23-alpine

# Setting up the working directory inside the container

WORKDIR /app

# Copy the Go source code into the container

COPY . .

# Building the Go application

RUN go build -o main .

# Command to run Go application

CMD ["./main"]

# Expose port 8000

EXPOSE 8080
  • FROM golang:1.23-alpine - We are using the official Go image to build and run the Go application. This image contains the necessary Go runtime and compiler.

  • WORKDIR /app - This command sets the working directory to /app inside the container. All subsequent operations will happen in this directory.

  • COPY . . - This copies all files from the current directory on the host machine (where the main.go file is located) to the /appdirectory inside the container.

  • RUN go build -o main . - This command compiles the Go application and outputs the binary executable with the name main.

  • CMD ["./main"] - This specifies the command to run the Go application when the container starts. It will run the compiled binary main.

  • EXPOSE 8080 - Exposes port 8080, which is the port on which the Go application will listen for HTTP requests.


  1. Python Flask Application :

    Problem statement:

    In this project, we will create a simple web API using Flask, a lightweight Python web framework, and containerize the application with Docker.

    Solution:

# Use the official Python image as the base image
FROM python:3.9

# Set the working directory inside the container
WORKDIR /app

# Copy the application files into the container
COPY . .

# Install Python dependencies
RUN pip install -r requirements.txt

# Command to run the Flask application
CMD ["python", "app.py"]

# Expose port 5000
EXPOSE 5000
  • FROM python:3.9 : This line uses the official Python 3.9 image as the base image. It contains Python and pip, which are required for the Flask application.

  • WORKDIR /app : The working directory is set to /app inside the container. This is where the application files will be placed.

  • COPY . . : This copies the application files (including app.py and requirements.txt) into the container’s /app directory.

  • RUN pip install -r requirements.txt : This installs the dependencies (Flask in this case) from the requirements.txt file.

  • CMD ["python", "app.py"] : This specifies the command to run the Flask application. When the container starts, it runs the Flask server.

  • EXPOSE 5000 : Exposes port 5000, the default port for Flask applications.

Problems I encountered:

  • Port already in use:

    docker run -d -p 5000:5000 flask-app

    The error message indicated that Docker cannot bind to port 5000 because another process was already using it.

How I solved it:

  1. First Method:

    1. Identify the Process Using Port 5000

    Run the following command to find the process using the port:

     lsof -i :5000
    

    This will list the details of the process, including the process ID (PID).

    2. Kill the Process (If Safe to Do So)

    If the process using port 5000 is not needed, terminate it using:

     kill -9 <PID>
    

    Replace <PID> with the process ID found in the previous step.

Second Method:

If we cannot or do not want to terminate the other process, we can use a different port for our Docker container. Update the port mapping in your docker run

docker run -p 5001:5000 flask-app

  1. Simple HTTP Server in Java:

    Problem Statement:

    Create a simple HTTP server in Java that listens on port 8080 and displays a message ("Hello from Java HTTP Server!") when accessed in a browser. Containerize this application using Docker so that the server can run inside a container.

    Solution:

# Use OpenJDK with JDK instead of JRE
FROM openjdk:11-jdk-slim

# Set the working directory inside the container
WORKDIR /app

# Copy the Java source code to the container
COPY src/Main.java .

# Compile the Java file
RUN javac Main.java

# Expose port 8080
EXPOSE 8080

# Command to run the application
CMD ["java", "Main"]
  • openjdk:11-jre-slim:
    This is a lightweight runtime image meant for running Java applications, but it does not include the javac compiler.

  • openjdk:11-jdk-slim:
    This is a lightweight development image that includes both the Java runtime and the javac compiler, which is needed to compile Java source files.


  1. Simple C++ HTTP Server:

    Problem Statement:

    Develop and containerize a simple C++ application that runs an HTTP server. When accessed on a browser or via curl, it will display a "Welcome to the C++ HTTP Server!" message. The app should be served on port 9090.

    Solution:

# Use a lightweight C++ base image
FROM gcc:latest

# Set working directory inside the container
WORKDIR /app

# Copy the source code into the container
COPY src/main.cpp .

# Compile the C++ source code
RUN g++ -o server main.cpp

# Expose port 9090
EXPOSE 9090

# Command to run the server
CMD ["./server"]
  • FROM gcc:latest:

    This is the base image containing the GCC compiler required for building C++ applications.


Resources:

Source code: https://github.com/nsahil992/Docker-Projects


Thank you for reading! 🙏

If you enjoyed this post and found it helpful, consider subscribing to my newsletter to stay updated with my latest work and insights. You can also connect with me on LinkedIn or X. Let’s stay connected and keep learning together! 🚀

LinkedIn: https://www.linkedin.com/in/nsahil992

X: https://twitter.com/nsahil992