DEV Community

Cover image for Getting Started with Docker: Containerization Made Easy ๐Ÿณ
Matt Ryan
Matt Ryan

Posted on

Getting Started with Docker: Containerization Made Easy ๐Ÿณ

Welcome to the world of Docker! If you've heard the buzz about containerization and are wondering what it's all about, you're in the right place.

Docker is a fantastic tool that makes it super easy to create, deploy, and run applications by using containers.

We'll be using Node.js, a popular and versatile JavaScript runtime, to demonstrate how Docker can simplify your development process, streamline deployment, and ensure consistency across environments.

While this guide focuses on Node.js to illustrate Docker's capabilities, it's important to note that Docker's versatility extends far beyond any single technology or programming language. Docker provides a consistent and isolated environment for virtually any application, regardless of the stack or framework.

Whether you're working with Python, Ruby, Java, .NET, or even complex database systems and microservices architectures, Docker's containerization technology ensures that your applications run seamlessly in any environment.

So let's dive in! ๐ŸŠโ€โ™‚๏ธ

What is Docker? ๐Ÿค”

Docker is a platform for developing, shipping, and running applications in containers. Containers allow you to package up an application with all of its parts, such as libraries and other dependencies, and ship it as one package. Think of it like a shipping container for code โ€“ consistent, isolated, and easy to move around! ๐Ÿ“ฆ

Why Use Docker? ๐Ÿš€

  • Consistency: Docker ensures that your application works the same in different environments.
  • Isolation: Containers are isolated from each other and the host system.
  • Microservices: Docker is ideal for microservice architectures.
  • Portability: Move your containers from your local machine to production without a hitch.

Installing Docker ๐Ÿ› ๏ธ

To get started, you need to install Docker. It's available for Windows, macOS, and Linux. Visit the Docker website and download the appropriate version for your OS.

Your First Docker Container ๐ŸŒŸ

Let's run our first container!

  1. Open your terminal and type:
   docker run hello-world
Enter fullscreen mode Exit fullscreen mode

This command downloads a test image and runs it in a container. When the container runs, it prints an informational message and exits.

Congratulations! ๐ŸŽ‰ You've just run your first Docker container.

Building Your First Docker Image ๐Ÿ“ฆ

Create a directory for your project and move into it:

mkdir mynodeapp
cd mynodeapp
Enter fullscreen mode Exit fullscreen mode

Create a Dockerfile. This file will define what goes on in the environment inside your container.

Let's create a simple example of a Dockerfile for a Node.js application. This example assumes you have a basic Node.js application with a package.json file. Here's how you can set up your Docker environment:

Step 1: Create a Node.js Application

If you already have a Node.js app, you can skip this step. Otherwise, create a simple "Hello World" app:

Initialize a new Node.js project: Initialize a Node.js project in the mynodeapp directory.

npm init -y
Enter fullscreen mode Exit fullscreen mode

Install Express: Since this app uses Express.js, install it as a dependency.

npm install express
Enter fullscreen mode Exit fullscreen mode

Create an index.js file: This will be your main application file. For a simple "Hello World" app, you can add the following content:

// index.js
const express = require('express');
const app = express();
const PORT = 3000;

app.get('/', (req, res) => {
  res.send('Hello World!');
});

app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});
Enter fullscreen mode Exit fullscreen mode

Step 2: Create a Dockerfile

Now, create a Dockerfile in the same directory as your Node.js application.

Create the Dockerfile: Without any extension, just named Dockerfile.

touch Dockerfile
Enter fullscreen mode Exit fullscreen mode

Edit the Dockerfile: Open the Dockerfile in nano or vim and add the following content:

# Use an official Node runtime as a parent image
FROM node:14

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

# Copy package.json and package-lock.json
COPY package*.json ./

# Install any needed packages
RUN npm install

# Bundle app source
COPY . .

# Make port 3000 available to the world outside this container
EXPOSE 3000

# Define environment variable
ENV NAME World

# Run app when the container launches
CMD ["node", "index.js"]
Enter fullscreen mode Exit fullscreen mode

Step 3: Building and Running Your Docker Container

Build your Docker image: To build your Docker image, use the docker build command followed by options and the path to your Dockerfile. The -t option allows you to tag your image so you can easily reference it later.

In this example, the image is tagged as mynodeapp. The . at the end of the command tells Docker to look for the Dockerfile in the current directory.

docker build -t mynodeapp .
Enter fullscreen mode Exit fullscreen mode

Run your Docker container: After building your Docker image, you can run it as a container using the docker run command. The -p option maps a port on your host machine to a port in the container. In this command, 49160:3000 maps port 3000 inside the container (where your Node.js app is listening) to port 49160 on your host machine.

The -d option runs the container in detached mode, meaning the container runs in the background. The mynodeapp at the end of the command specifies the name of the image to use.

docker run -p 49160:3000 -d mynodeapp
Enter fullscreen mode Exit fullscreen mode

This command will start a new container instance from the mynodeapp image, making your Node.js application accessible via http://localhost:49160 on your local machine.

This basic example demonstrates how to containerize a simple Node.js application using Docker. You can modify the application logic and Dockerfile as needed for more complex applications.

Docker Compose for Multi-container Applications ๐Ÿ“Š

Docker Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your applicationโ€™s services, networks, and volumes.

In this example, we'll use Docker Compose to run our Node.js application along with a Redis service.

Step 1: Create a docker-compose.yml File

In your Node.js application directory, create a file named docker-compose.yml. This file will define two services: your Node.js app and a Redis server.

version: '3.8'

services:
  app:
    build: .
    ports:
      - "49160:3000"
    depends_on:
      - redis
    environment:
      - REDIS_HOST=redis
      - REDIS_PORT=6379

  redis:
    image: "redis:alpine"
    ports:
      - "6379:6379"
Enter fullscreen mode Exit fullscreen mode

This configuration does the following:

  • version: Specifies the version of the Docker Compose file format. 3.8 is a version that supports most recent features.
  • services: This section defines the different containers (services) that make up your application.
  • app: This is the name of your Node.js service. You can choose any name that makes sense for your application.
  • build: This directive tells Docker Compose to build an image from the Dockerfile located in the current directory (.).
  • ports: Maps the port on your host machine to the port in the container. In this case, port 3000 inside the container (where the Node.js app runs) is mapped to port 49160 on your host.
  • depends_on: Specifies that the app service depends on the redis service. This ensures that the redis service starts before the app service.
  • environment: Sets environment variables inside the container. Here, it's defining the host and port for the Redis server, which your Node.js application can use to connect to Redis.
  • redis: This is the name of the Redis service in your application.
  • image: Specifies the Docker image to use for the Redis service. In this case, it's using the redis image with the alpine tag, which is a lightweight version of Redis.
  • ports (for Redis): Similar to the app service, this maps the Redis port inside the container (6379) to the same port on the host machine.

This docker-compose.yml file creates a simple yet effective setup for a Node.js application with a Redis server, providing a solid example of how Docker Compose can manage multi-container environments.

Step 2: Update Your Node.js Application to Use Redis

Modify your Node.js application to interact with Redis. For example, you might want to use Redis for caching. Make sure to install any necessary Redis client libraries for Node.js, such as redis.

First, ensure you have the Redis client installed in your Node.js project:

npm install redis
Enter fullscreen mode Exit fullscreen mode

Now, update your index.js file as follows:

const express = require('express');
const redis = require('redis');
const app = express();
const PORT = 3000;

// Connect to Redis
const redisClient = redis.createClient({
  host: 'redis', // This matches the service name in docker-compose
  port: 6379
});

redisClient.on('error', (err) => console.log('Redis Client Error', err));

app.get('/', async (req, res) => {
  const cacheKey = 'homepage';
  // Check if data is in Redis
  redisClient.get(cacheKey, (err, cachedData) => {
    if (err) throw err;

    if (cachedData) {
      console.log('Cache hit');
      res.send(`Hello World from cache!`);
    } else {
      console.log('Cache miss');
      // Set data in Redis with an expiry (e.g., 3600 seconds)
      redisClient.setex(cacheKey, 3600, 'Hello World!');
      res.send('Hello World set in cache!');
    }
  });
});

app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});
Enter fullscreen mode Exit fullscreen mode

In this updated index.js, your Node.js application now uses Redis to cache the string "Hello World!". When a request is made to the root route (/), the application first checks if the data is available in the Redis cache. If it's a cache hit, it retrieves the data from Redis. If it's a cache miss, it sets the data in Redis and returns the response.

Step 3: Run Docker Compose

In the directory containing your docker-compose.yml file, start your services:

docker-compose up -d
Enter fullscreen mode Exit fullscreen mode

This command will build the images for your Node.js app and the Redis service and then start the containers as defined in your Docker Compose file.

Step 4: Access Your Application

Your Node.js application should now be accessible at http://localhost:49160, and it will be able to interact with the Redis service.

Step 5: Managing Services

To stop your services, use:

docker-compose down
Enter fullscreen mode Exit fullscreen mode

To rebuild and start the services after making changes, use:

docker-compose up -d --build
Enter fullscreen mode Exit fullscreen mode

You've now successfully set up a multi-container application using Docker Compose, featuring your Node.js application and a Redis server. This setup is ideal for developing applications that rely on external services like databases, caches, or other microservices.

Essential Docker Commands ๐Ÿ“‡

Docker is a powerful platform for building, running, and managing containers. Mastering its commands is key to effectively managing your containerized applications.

Below are some essential Docker commands divided into basic and advanced categories, providing a comprehensive toolkit for Docker users.

Basic Commands

The basic Docker commands are the foundation for container management. They cover everyday tasks such as running containers, managing container lifecycles, and handling images.

docker run: Creates and starts a container from an image.

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
Enter fullscreen mode Exit fullscreen mode

docker ps: Lists running containers. Use docker ps -a to show all containers.

docker ps [OPTIONS]
Enter fullscreen mode Exit fullscreen mode

docker stop: Stops one or more running containers.

docker stop [OPTIONS] CONTAINER [CONTAINER...]
Enter fullscreen mode Exit fullscreen mode

docker rm: Removes one or more containers.

docker rm [OPTIONS] CONTAINER [CONTAINER...]
Enter fullscreen mode Exit fullscreen mode

docker images: Lists the images available locally.

docker images [OPTIONS] [REPOSITORY[:TAG]]
Enter fullscreen mode Exit fullscreen mode

docker rmi: Removes one or more images.

docker rmi [OPTIONS] IMAGE [IMAGE...]
Enter fullscreen mode Exit fullscreen mode

docker pull: Pulls an image or a repository from a registry.

docker pull [OPTIONS] NAME[:TAG|@DIGEST]
Enter fullscreen mode Exit fullscreen mode

docker exec: Runs a command in a running container.

docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
Enter fullscreen mode Exit fullscreen mode

Advanced Commands

Advanced Docker commands offer more complex functionalities for managing networks, volumes, and detailed container and image inspections, catering to more specific and complex container management requirements.

docker build: Builds an image from a Dockerfile.

docker build [OPTIONS] PATH | URL | -
Enter fullscreen mode Exit fullscreen mode

docker logs: Fetches the logs of a container.

docker logs [OPTIONS] CONTAINER
Enter fullscreen mode Exit fullscreen mode

docker network: Manages networks. You can create, list, inspect, remove, etc.

docker network [COMMAND]
Enter fullscreen mode Exit fullscreen mode

docker volume: Manages volumes. Similar to network commands, it can create, list, remove, etc.

docker volume [COMMAND]
Enter fullscreen mode Exit fullscreen mode

docker compose: Manages multi-container Docker applications (requires Docker Compose).

docker compose [COMMAND]
Enter fullscreen mode Exit fullscreen mode

docker inspect: Returns detailed information on Docker objects (containers, images, etc.).

docker inspect [OPTIONS] NAME|ID [NAME|ID...]
Enter fullscreen mode Exit fullscreen mode

docker stats: Displays a live stream of container(s) resource usage statistics.

docker stats [OPTIONS] [CONTAINER...]
Enter fullscreen mode Exit fullscreen mode

docker cp: Copies files/folders between a container and the local filesystem.

docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-
docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH
Enter fullscreen mode Exit fullscreen mode

Conclusion ๐ŸŽ‰

Congratulations! You've just scratched the surface of Docker. There's so much more to explore. Dive into the Docker documentation for more in-depth knowledge.

Happy Dockerizing! ๐Ÿณ

Top comments (1)

Collapse
 
ajeetraina profile image
Ajeet Singh Raina

You can save a lot of your time in using Docker Init for NodeJS collabnix.com/introducing-docker-i...