Skip to content

[DevOps] Containerize Application with Docker Multi-Stage Build and Docker Compose #10

Description

@KarenZita01

Description

To ensure consistent environments across development, staging, and production, the EquipChain backend must be containerized using Docker. This issue creates a production-grade Docker multi-stage build configuration along with a Docker Compose setup for local development that includes the API server plus any required services (Redis for caching, etc.).

The Dockerfile should use a multi-stage build approach: the builder stage installs all dependencies (including devDependencies), runs tests, and optionally lints the code; the production stage copies only the necessary artifacts (production dependencies, source files) to a minimal Node.js image (e.g., node:20-alpine). The production image should run as a non-root user for security and should have NODE_ENV=production set.

The Docker Compose configuration should define the api service (built from the Dockerfile) along with a redis service for the caching layer (Issue #12) and any other dependencies. Configuration should come from environment variables via an .env file or Compose environment section. Health checks should be defined for each service, and proper network isolation should be configured using named networks.

Technical Context & Impact

  • Dependencies: Docker Engine 24+, Docker Compose v2+. No changes to application code required — just build configuration files.
  • Architecture: Dockerfile at project root, docker-compose.yml at project root, .dockerignore to exclude node_modules, .git, and log files.
  • Impact: Containerization is essential for reproducible deployments. It eliminates "it works on my machine" issues and simplifies scaling. Docker Compose enables a one-command local development environment with all required services running.

Step-by-Step Implementation Guide

  1. Create Dockerfile: Write Dockerfile with two stages. Builder: FROM node:20-alpine AS builder, copy package*.json, run npm ci, copy source code, run npm test. Production: FROM node:20-alpine, create node:node user, copy production node_modules and source from builder, expose port 3000, run USER node, CMD ["node", "src/index.js"].
  2. Create .dockerignore: Write .dockerignore ignoring node_modules, .git, .env, *.md, coverage/, tests/, .github/.
  3. Create Docker Compose File: Write docker-compose.yml with services: api (build context ., env_file: .env, ports: "3000:3000", depends_on: redis, healthcheck), redis (image: redis:7-alpine, ports: "6379:6379", healthcheck, volumes for persistence).
  4. Create Helper Scripts: Add docker-compose.override.yml for development with volume mounts for hot-reloading. Add scripts/docker-build.sh and scripts/docker-run.sh for convenience.
  5. Update Documentation: Add Docker setup instructions to README or a new CONTRIBUTING.md — how to build, run, stop, and clean up containers.

Verification & Testing Steps

  1. Run docker build -t equipchain-api . and verify the build completes successfully, showing both stages in the output.
  2. Run docker run --rm -p 3000:3000 equipchain-api and verify GET http://localhost:3000/ returns the expected JSON response.
  3. Run docker compose up -d and verify both api and redis containers start. Run docker compose ps to check status.
  4. Run docker compose logs api to verify the API logs indicate successful startup and Redis connection.
  5. Run docker compose down and verify all containers are stopped and networks removed. Run docker compose down -v to also remove volumes.

Metadata

Metadata

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial Campaign | FWC26Campaign: Official Campaign | FWC26

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions