Practice Lab Guide

Project 13: Containerized IoT Backend Deployment

Deploy a multi-container test and production backend using Docker Compose health checks and automated test runs.
Domain
Container Security & Orchestration
Difficulty
⭐⭐⭐⭐☆ (Advanced)
Course Module
Deployment & DevOps for IoT
Deliverables
Multi-container Docker Compose Config
1. Docker Compose Dependency & Health Check Architecture

If integration tests start before the target backend API is ready to accept connections, the test runner will fail. The diagram below illustrates how Docker Compose coordinates container startup. The `backend` container starts first. Its health check loops every 5 seconds, querying the `/health` endpoint. Once the server returns a 200 OK status, the `test-runner` container starts, runs the test suite, and outputs the results.

docker-compose up Launches container stack Service: backend Express Server (Port 3000) Health Check: curl /health Status: HEALTHY Returns 200 OK payload Service: test-runner Jest Test Runner Supertest targets 'backend:3000' Runs: npm run test Exits immediately after run depends_on: healthy
2. Part 1: Step-by-Step Container Deployment Commands

Follow these detailed steps to build the test configuration files, define compose tasks, configure container health checks, and run the test suite.

STEP 1

Launch VM Terminal and Navigate to Project Workspace

Boot up your VirtualBox Ubuntu machine. Open the terminal (Ctrl+Alt+T) and change directories to the project folder.

ubuntu@iot-vm:~$ cd ~/workspace/backend_scaffold
We change the working directory of our shell to the backend workspace, where we will configure the Docker deployment files.
STEP 2

Create the Test Environment Dockerfile

Open a new file in gedit to write the Docker configuration for the test environment.

ubuntu@iot-vm:~/workspace/backend_scaffold$ gedit Dockerfile.test &
We open `Dockerfile.test` inside the workspace folder to define the environment for running the automated integration tests.
STEP 3

Configure Multi-Container Orchestration in docker-compose.yml

Open `docker-compose.yml` to define the backend and test-runner services, including health checks and dependency rules.

ubuntu@iot-vm:~/workspace/backend_scaffold$ gedit docker-compose.yml &
We open `docker-compose.yml` to configure the database, backend, and test-runner containers, setting up port routing and startup dependencies.
STEP 4

Start the Containerized Environment

Build the images and start the services using Docker Compose. The terminal will log the compilation and startup sequence.

ubuntu@iot-vm:~/workspace/backend_scaffold$ sudo docker-compose up --build --exit-code-from test-runner
We run `docker-compose up` with the `--exit-code-from` flag as root to start the services and exit Compose once the test-runner finishes executing the test suite.
STEP 5

Monitor Active Container Logs

Query the container logs in a new terminal window to verify that the Express server started successfully and the health check is active.

ubuntu@iot-vm:~/workspace/backend_scaffold$ sudo docker logs iot_node_backend
We run `docker logs` as root to view the console output of the backend container, verifying that the server started and is handling health-check requests.
3. Multi-Container Networking Model

The diagram below maps the network paths on the virtual Docker bridge network, illustrating how the test-runner container resolves and queries the backend service.

Container: test-runner Queries: http://web-backend:3000 Docker DNS resolves hostname Docker Bridge Network Subnet: 172.20.0.0/16 Routes traffic between containers Container: web-backend IP: 172.20.0.2 Handles incoming API requests
4. Part 2: Complete Docker Configurations

Below is the complete C++ firmware code showing how abstract inheritance interfaces work, followed by the complete Python script to listen to the serial port and print the data.

Asset 1: Test Image Blueprint Configuration (`Dockerfile.test`)

Line-by-Line Code Breakdown

# Dockerfile for Integration Test Runner Service FROM node:20-alpine WORKDIR /app COPY package*.json ./ COPY tsconfig.json ./ COPY jest.config.js ./ RUN npm install COPY . . CMD ["npm", "run", "test"]

Asset 2: Multi-Container Composition Orchestrator File (`docker-compose.yml`)

Line-by-Line Code Breakdown

# Multi-Container Deployment Orchestration File version: '3.8' services: web-backend: build: . container_name: iot_node_backend ports: - "3000:3000" environment: - PORT=3000 - NODE_ENV=production restart: always healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/health"] interval: 5s timeout: 3s retries: 3 test-runner: build: context: . dockerfile: Dockerfile.test container_name: iot_node_test_runner depends_on: web-backend: condition: service_healthy environment: - NODE_ENV=test
5. Deliverables Summary

Created Workspace Assets

  • Integration test Docker configuration: Dockerfile.test.
  • Orchestrator configuration file: docker-compose.yml.

Verification Proof

  • Build output logs showing both containers compiling and starting.
  • Compose console logs showing the test-runner container starting only after the backend passes the health check, executing the test suite, and exiting with status code 0.
6. Closing Explanation: Why We Did This & What It Accomplishes

Architectural Intent & Operational Impact

Why We Did This

What This Accomplishes