It works on my machine... Not on yours... But why? Let's talk Docker!

For Dev & DevOps geeks, ensuring that your application runs smoothly across different environments can often be a daunting task. A phrase commonly heard among them when troubleshooting such issues is "This works on my machine, not on yours... But why?"

It works on my machine... Not on yours... But why? Let's talk Docker!
One desperate attempt to create a meme for the first time. 😄
Enter Docker, a powerful tool that can help solve this problem by containerizing your applications. Let's explore Docker with simple analogies.
In the popular Malayalam movie "Nattuvishesham", there's a memorable scene where the character played by actor Mukesh asks "But Why?" in a humorous tone. Similarly, Docker helps developers answer the "But Why?" question by providing a reliable and consistent way to package and deploy applications, thereby eliminating the frustration of environment inconsistencies.

What is Docker?

💡
Docker is an open platform that helps developers build, share, run, and verify applications anywhere — without tedious environment configuration or management.

Simplifying Docker (An analogy)

Imagine you're a baker, and you want to share your special cake recipe with friends. However, each friend has a different kitchen setup and ingredients availability, which could affect how the cake turns out when they bake it.

The Dockerfile is like the magic recipe box that ensures everyone bakes the cake exactly the same way, regardless of their kitchen setup. Instead of just giving your friends the recipe, you pack the recipe, all the necessary ingredients, and even the specific oven settings into a special box — a Docker container.

Here’s how Docker works in this analogy:

  1. Recipe: Your application's code and configuration are like the cake recipe. It tells Docker how to set up and run your application.
  2. Ingredients: These are the dependencies and libraries your application needs to work correctly. Docker packs all of them into the container.
  3. Oven Settings: In Docker, this is like the environment in which your application runs — whether it's Linux, Windows, or Mac. Docker ensures your application runs consistently across different environments.

Dockerfile

# Use an official Node.js runtime as a parent image
FROM node:latest

# Set the working directory in the container
WORKDIR /usr/src/app

# Copy package.json and package-lock.json to the working directory
COPY package*.json ./

# Install dependencies
RUN npm install

# Copy the rest of the application code to the working directory
COPY . .

# Expose the port your app runs on
EXPOSE 3000

# Command to run the application
CMD ["node", "app.js"]

Example of a simple Dockerfile

Let's break down this Dockerfile, step by step, using our cake analogy:

  • Base Image (FROM node:latest)
    This is like choosing the right type of kitchen to bake your cake. Here, we're using a Node.js kitchen (runtime environment).
  • Working Directory (WORKDIR /usr/src/app)
    This sets up a clean and organized space in the kitchen where all the cake-making will happen.
  • Copy Ingredients (COPY package*.json ./)
    This step copies the ingredient list (package.json) to the kitchen.
  • Install Dependencies (RUN npm install)
    Just like measuring and mixing the ingredients, this step installs all the necessary dependencies (ingredients) listed in package.json.
  • Copy Recipe (COPY . .)
    This copies the actual cake recipe (all the remaining code files) to the kitchen workspace.
  • Expose Port (EXPOSE 3000)
    Think of this as opening a window to let the delicious cake aroma (application) spread outside the kitchen. Here, it exposes port 3000 so the app can be accessed.
  • Command to Start Baking (CMD ["node", "app.js"])
    Finally, this command starts the baking process (runs the application).

By using Docker containers, you can share your application (or recipe) with others knowing they'll get the same result, regardless of their local setup. It keeps everything self-contained and portable, making development and deployment smoother and more reliable.

Screenshot of Docker Desktop - running 3 docker containers for a sample Node.js project.

What is Docker Compose?

💡
Docker Compose extends the idea of Docker by orchestrating multiple containers, allowing you to manage complex applications as easily as serving a dessert buffet.

Docker vs Docker Compose Explained (An analogy)

Imagine you're not just baking one cake but preparing an entire dessert buffet for a party. Each dessert requires different recipes, ingredients, and baking times. Docker Compose helps you manage this complexity by orchestrating multiple containers, each handling a different dessert, yet ensuring they all work together seamlessly.

Docker (Single Recipe)

  1. Recipe: Each dessert's recipe represents your application's code and configuration in Docker. For instance, one recipe might be for a cake (Node.js app), and another for cookies (Python app).
  2. Ingredients: Ingredients are like the dependencies and libraries each dessert (application) needs. Docker packs these into separate containers to keep them isolated and prevent flavors (dependencies) from mixing.
  3. Oven Settings: Docker ensures each dessert bakes consistently across different kitchens (environments), whether it's on Linux, Windows, or Mac.

Docker Compose (Dessert Buffet)

Now, let's introduce Docker Compose to manage your dessert buffet:

  1. Dessert Menu (docker-compose.yml): Think of docker-compose.yml as your party's dessert menu. It lists all the desserts (services) you want to serve at the party and how they should be prepared.
version: '3.8'
services:
  cake:
    build: ./cake-app
    ports:
      - "3000:3000"
  cookies:
    build: ./cookies-app
    • cake and cookies are two services defined in your docker-compose.yml. Each corresponds to a different Docker container.
    • build: ./cake-app and build: ./cookies-app specify where to find each dessert's recipe (Dockerfile).
  1. Party Setup: Before the party (deployment), you use Docker Compose to set up the dessert buffet.
docker-compose up
    • Docker Compose builds each dessert according to its recipe and starts all containers based on your docker-compose.yml.
  1. Enjoy the Party: With Docker Compose, each dessert (application) is managed separately but works together smoothly, just like different containers on a dessert buffet table.

Conclusion

Docker simplifies application deployment by packaging applications and their dependencies into isolated containers, ensuring consistency across different environments. Docker Compose extends this concept by orchestrating multiple containers, allowing you to manage complex applications as easily as serving a dessert buffet.

By using Docker and Docker Compose, you can confidently deploy your applications knowing they'll work the same way everywhere — a sweet solution to modern development challenges!