Swiftorial Logo
Home
Swift Lessons
Matchuup
CodeSnaps
Tutorials
Career
Resources

Docker Compose Files

Docker Compose is a tool for defining and running multi-container Docker applications. This guide covers key concepts, steps to create and manage Docker Compose files, examples, and best practices for using Docker Compose with Express.js applications.

Key Concepts of Docker Compose Files

  • Service: Defines a container to run, including the image, ports, volumes, and networks.
  • Network: Configures custom Docker networks for inter-container communication.
  • Volume: Defines data storage and sharing between containers and the host system.
  • Compose File: A YAML file used to configure application services, networks, and volumes.

Setting Up the Project

Initialize a new Express.js project and create a Dockerfile:

// Initialize a new project
// npm init -y

// Install Express
// npm install express

// Create the project structure
// mkdir src
// touch src/index.js Dockerfile .dockerignore .gitignore docker-compose.yml

// .gitignore
node_modules
.env

// .dockerignore
node_modules
npm-debug.log

Creating an Express Application

Create a simple Express application:

Example: index.js

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

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

app.listen(port, () => {
    console.log(`Server running at http://localhost:${port}/`);
});

Creating a Dockerfile

Create a Dockerfile to containerize your Express application:

Example: Dockerfile

// Dockerfile
FROM node:14

# Create app directory
WORKDIR /usr/src/app

# Install app dependencies
COPY package*.json ./
RUN npm install

# Bundle app source
COPY . .

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

# Run app when the container launches
CMD ["node", "src/index.js"]

Creating a Docker Compose File

Create a docker-compose.yml file to define the services for your Docker Compose setup:

Example: docker-compose.yml

// docker-compose.yml
version: '3.8'
services:
  web:
    build: .
    ports:
      - "3000:3000"
    networks:
      - webnet
    volumes:
      - .:/usr/src/app
    environment:
      - NODE_ENV=development

networks:
  webnet:

Running Docker Compose

Use Docker Compose to build and run the services defined in the docker-compose.yml file:

// Build and run the services
docker-compose up --build

// Open http://localhost:3000 in your browser to see the application running

Managing Docker Compose

Use Docker Compose commands to manage your multi-container application:

List Running Services

// List running services
docker-compose ps

Stopping Services

// Stop services
docker-compose stop

Removing Services

// Remove services and associated resources
docker-compose down

Adding a Database Service

Extend your docker-compose.yml file to include a database service:

Example: docker-compose.yml with Database

// docker-compose.yml
version: '3.8'
services:
  web:
    build: .
    ports:
      - "3000:3000"
    networks:
      - webnet
    volumes:
      - .:/usr/src/app
    environment:
      - NODE_ENV=development
      - MONGO_URL=mongodb://mongo:27017/mydatabase

  mongo:
    image: mongo:latest
    networks:
      - webnet
    volumes:
      - mongo-data:/data/db

networks:
  webnet:

volumes:
  mongo-data:

Best Practices for Using Docker Compose

  • Use Volumes for Data Persistence: Use named volumes to persist data across container restarts and removals.
  • Use Networks for Inter-Container Communication: Define custom networks to enable communication between containers.
  • Use Environment Variables for Configuration: Store configuration data in environment variables to keep your application flexible and secure.
  • Separate Development and Production Configurations: Use different Compose files or override configurations for development and production environments.
  • Keep Compose Files DRY: Avoid repetition in your Compose files by using YAML anchors and aliases.

Testing Docker Compose Integration

Test your Docker Compose setup to ensure it works correctly:

Example: Testing with Mocha and Chai

// Install Mocha and Chai
// npm install --save-dev mocha chai

// test/app.test.js
const chai = require('chai');
const expect = chai.expect;
const axios = require('axios');

describe('Express App', () => {
    it('should return Hello, Docker Compose!', async () => {
        const response = await axios.get('http://localhost:3000');
        expect(response.data).to.equal('Hello, Docker Compose!');
    });
});

// Add test script to package.json
// "scripts": {
//   "test": "mocha"
// }

// Run tests
// docker-compose up --build
// npm test

Key Points

  • Service: Defines a container to run, including the image, ports, volumes, and networks.
  • Network: Configures custom Docker networks for inter-container communication.
  • Volume: Defines data storage and sharing between containers and the host system.
  • Compose File: A YAML file used to configure application services, networks, and volumes.
  • Follow best practices for using Docker Compose, such as using volumes for data persistence, networks for inter-container communication, environment variables for configuration, separating development and production configurations, and keeping Compose files DRY.

Conclusion

Docker Compose is a powerful tool for defining and running multi-container Docker applications. By understanding and implementing the key concepts, steps, examples, and best practices covered in this guide, you can effectively use Docker Compose to manage your Express.js applications. Happy coding!