mirror of
https://github.com/docker/docs.git
synced 2026-03-28 23:08:49 +07:00
This PR introduces a comprehensive, language-specific guide for containerizing Node.js applications using Docker, aimed at helping developers streamline development, testing, and deployment workflows. It includes hands-on steps and real-world examples to configure CI/CD pipelines using GitHub Actions, following modern DevOps best practices. **What’s Included** - Step-by-step instructions to containerize Node.js applications using Docker. - Configuration for a local development environment inside containers with automatic reloads. - Guidance on running unit and integration tests within Docker containers. - Full CI/CD pipeline setup using GitHub Actions for automated builds, tests, and deployments. - Deployment instructions for a local Kubernetes cluster to validate production readiness. **Credits** [Kristiyan Velkov](https://www.linkedin.com/in/kristiyanvelkov/), Docker Captain. ## Reviews <!-- Notes for reviewers here --> <!-- List applicable reviews (optionally @tag reviewers) --> - [x] Technical review - [x] Editorial review - [ ] Product review
229 lines
7.5 KiB
Markdown
229 lines
7.5 KiB
Markdown
---
|
||
title: Run Node.js tests in a container
|
||
linkTitle: Run your tests
|
||
weight: 30
|
||
keywords: node.js, node, test
|
||
description: Learn how to run your Node.js tests in a container.
|
||
aliases:
|
||
- /language/nodejs/run-tests/
|
||
- /guides/language/nodejs/run-tests/
|
||
---
|
||
|
||
## Prerequisites
|
||
|
||
Complete all the previous sections of this guide, starting with [Containerize a Node.js application](containerize.md).
|
||
|
||
## Overview
|
||
|
||
Testing is a core part of building reliable software. Whether you're writing unit tests, integration tests, or end-to-end tests, running them consistently across environments matters. Docker makes this easy by giving you the same setup locally, in CI/CD, and during image builds.
|
||
|
||
## Run tests when developing locally
|
||
|
||
The sample application uses Vitest for testing, and it already includes tests for React components, custom hooks, API routes, database operations, and utility functions.
|
||
|
||
### Run tests locally (without Docker)
|
||
|
||
```console
|
||
$ npm run test
|
||
```
|
||
|
||
### Add test service to Docker Compose
|
||
|
||
To run tests in a containerized environment, you need to add a dedicated test service to your `compose.yml` file. Add the following service configuration:
|
||
|
||
```yaml
|
||
services:
|
||
# ... existing services ...
|
||
|
||
# ========================================
|
||
# Test Service
|
||
# ========================================
|
||
app-test:
|
||
build:
|
||
context: .
|
||
dockerfile: Dockerfile
|
||
target: test
|
||
container_name: todoapp-test
|
||
environment:
|
||
NODE_ENV: test
|
||
POSTGRES_HOST: db
|
||
POSTGRES_PORT: 5432
|
||
POSTGRES_DB: todoapp_test
|
||
POSTGRES_USER: todoapp
|
||
POSTGRES_PASSWORD: '${POSTGRES_PASSWORD:-todoapp_password}'
|
||
depends_on:
|
||
db:
|
||
condition: service_healthy
|
||
command: ['npm', 'run', 'test:coverage']
|
||
networks:
|
||
- todoapp-network
|
||
profiles:
|
||
- test
|
||
```
|
||
|
||
This test service configuration:
|
||
|
||
- **Builds from test stage**: Uses the `test` target from your multi-stage Dockerfile
|
||
- **Isolated test database**: Uses a separate `todoapp_test` database for testing
|
||
- **Profile-based**: Uses the `test` profile so it only runs when explicitly requested
|
||
- **Health dependency**: Waits for the database to be healthy before starting tests
|
||
|
||
### Run tests in a container
|
||
|
||
You can run tests using the dedicated test service:
|
||
|
||
```console
|
||
$ docker compose up app-test --build
|
||
```
|
||
|
||
Or run tests against the development service:
|
||
|
||
```console
|
||
$ docker compose run --rm app-dev npm run test
|
||
```
|
||
|
||
For a one-off test run with coverage:
|
||
|
||
```console
|
||
$ docker compose run --rm app-dev npm run test:coverage
|
||
```
|
||
|
||
### Run tests with coverage
|
||
|
||
To generate a coverage report:
|
||
|
||
```console
|
||
$ npm run test:coverage
|
||
```
|
||
|
||
You should see output like the following:
|
||
|
||
```console
|
||
> docker-nodejs-sample@1.0.0 test
|
||
> vitest --run
|
||
|
||
✓ src/server/__tests__/routes/todos.test.ts (5 tests) 16ms
|
||
✓ src/shared/utils/__tests__/validation.test.ts (15 tests) 6ms
|
||
✓ src/client/components/__tests__/LoadingSpinner.test.tsx (8 tests) 67ms
|
||
✓ src/server/database/__tests__/postgres.test.ts (13 tests) 136ms
|
||
✓ src/client/components/__tests__/ErrorMessage.test.tsx (8 tests) 127ms
|
||
✓ src/client/components/__tests__/TodoList.test.tsx (8 tests) 147ms
|
||
✓ src/client/components/__tests__/TodoItem.test.tsx (8 tests) 218ms
|
||
✓ src/client/__tests__/App.test.tsx (13 tests) 259ms
|
||
✓ src/client/components/__tests__/AddTodoForm.test.tsx (12 tests) 323ms
|
||
✓ src/client/hooks/__tests__/useTodos.test.ts (11 tests) 569ms
|
||
|
||
Test Files 9 passed (9)
|
||
Tests 88 passed (88)
|
||
Start at 20:57:19
|
||
Duration 4.41s (transform 1.79s, setup 2.66s, collect 5.38s, tests 4.61s, environment 14.07s, prepare 4.34s)
|
||
```
|
||
|
||
### Test structure
|
||
|
||
The test suite covers:
|
||
|
||
- **Client Components** (`src/client/components/__tests__/`): React component testing with React Testing Library
|
||
- **Custom Hooks** (`src/client/hooks/__tests__/`): React hooks testing with proper mocking
|
||
- **Server Routes** (`src/server/__tests__/routes/`): API endpoint testing
|
||
- **Database Layer** (`src/server/database/__tests__/`): PostgreSQL database operations testing
|
||
- **Utility Functions** (`src/shared/utils/__tests__/`): Validation and helper function testing
|
||
- **Integration Tests** (`src/client/__tests__/`): Full application integration testing
|
||
|
||
## Run tests when building
|
||
|
||
To run tests during the Docker build process, you need to add a dedicated test stage to your Dockerfile. If you haven't already added this stage, add the following to your multi-stage Dockerfile:
|
||
|
||
```dockerfile
|
||
# ========================================
|
||
# Test Stage
|
||
# ========================================
|
||
FROM build-deps AS test
|
||
|
||
# Set environment
|
||
ENV NODE_ENV=test \
|
||
CI=true
|
||
|
||
# Copy source files
|
||
COPY --chown=nodejs:nodejs . .
|
||
|
||
# Switch to non-root user
|
||
USER nodejs
|
||
|
||
# Run tests with coverage
|
||
CMD ["npm", "run", "test:coverage"]
|
||
```
|
||
|
||
This test stage:
|
||
|
||
- **Test environment**: Sets `NODE_ENV=test` and `CI=true` for proper test execution
|
||
- **Non-root user**: Runs tests as the `nodejs` user for security
|
||
- **Flexible execution**: Uses `CMD` instead of `RUN` to allow running tests during build or as a separate container
|
||
- **Coverage support**: Configured to run tests with coverage reporting
|
||
|
||
### Build and run tests during image build
|
||
|
||
To build an image that runs tests during the build process, you can create a custom Dockerfile or modify the existing one temporarily:
|
||
|
||
```console
|
||
$ docker build --target test -t node-docker-image-test .
|
||
```
|
||
|
||
### Run tests in a dedicated test container
|
||
|
||
The recommended approach is to use the test service defined in `compose.yml`:
|
||
|
||
```console
|
||
$ docker compose --profile test up app-test --build
|
||
```
|
||
|
||
Or run it as a one-off container:
|
||
|
||
```console
|
||
$ docker compose run --rm app-test
|
||
```
|
||
|
||
### Run tests with coverage in CI/CD
|
||
|
||
For continuous integration, you can run tests with coverage:
|
||
|
||
```console
|
||
$ docker build --target test --progress=plain --no-cache -t test-image .
|
||
$ docker run --rm test-image npm run test:coverage
|
||
```
|
||
|
||
You should see output containing the following:
|
||
|
||
```console
|
||
✓ src/server/__tests__/routes/todos.test.ts (5 tests) 16ms
|
||
✓ src/shared/utils/__tests__/validation.test.ts (15 tests) 6ms
|
||
✓ src/client/components/__tests__/LoadingSpinner.test.tsx (8 tests) 67ms
|
||
✓ src/server/database/__tests__/postgres.test.ts (13 tests) 136ms
|
||
✓ src/client/components/__tests__/ErrorMessage.test.tsx (8 tests) 127ms
|
||
✓ src/client/components/__tests__/TodoList.test.tsx (8 tests) 147ms
|
||
✓ src/client/components/__tests__/TodoItem.test.tsx (8 tests) 218ms
|
||
✓ src/client/__tests__/App.test.tsx (13 tests) 259ms
|
||
✓ src/client/components/__tests__/AddTodoForm.test.tsx (12 tests) 323ms
|
||
✓ src/client/hooks/__tests__/useTodos.test.ts (11 tests) 569ms
|
||
|
||
Test Files 9 passed (9)
|
||
Tests 88 passed (88)
|
||
Start at 20:57:19
|
||
Duration 4.41s (transform 1.79s, setup 2.66s, collect 5.38s, tests 4.61s, environment 14.07s, prepare 4.34s)
|
||
```
|
||
|
||
## Summary
|
||
|
||
In this section, you learned how to run tests when developing locally using Docker Compose and how to run tests when building your image.
|
||
|
||
Related information:
|
||
|
||
- [Dockerfile reference](/reference/dockerfile/) – Understand all Dockerfile instructions and syntax.
|
||
- [Best practices for writing Dockerfiles](/develop/develop-images/dockerfile_best-practices/) – Write efficient, maintainable, and secure Dockerfiles.
|
||
- [Compose file reference](/compose/compose-file/) – Learn the full syntax and options available for configuring services in `compose.yaml`.
|
||
- [`docker compose run` CLI reference](/reference/cli/docker/compose/run/) – Run one-off commands in a service container.
|
||
|
||
## Next steps
|
||
|
||
Next, you’ll learn how to set up a CI/CD pipeline using GitHub Actions.
|