Skip to content

Commit 4628f01

Browse files
Introduce devcontainer service container based development environment (#705)
All development is now done inside the container named `devcontainer` which contains all necessary tools and dependencies. The devcontainer orchestrates other service containers behind the scenes via Docker-from-Docker. Other containers are implementation details and should not be accessed directly. This is breaking change commit for development environment, so it is required to remove all the env files and start with fresh one. There are two supported ways to access the development environment. Recommended way is to use Development Containers with an IDE. The alternative is to use Docker Compose directly. Local development is officially no more supported. What more, documentation of contribution and CLAUDE.md was updated to match with the changes.
1 parent 6cee558 commit 4628f01

30 files changed

Lines changed: 788 additions & 169 deletions

.devcontainer/devcontainer.json

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "React UI (${localWorkspaceFolderBasename})",
3+
"initializeCommand": "bash ./setup.sh",
4+
"dockerComposeFile": [
5+
"../docker-compose.yml"
6+
],
7+
"service": "devcontainer",
8+
"shutdownAction": "stopCompose",
9+
"workspaceFolder": "/workspace",
10+
"forwardPorts": [
11+
"docs:8000"
12+
],
13+
"portsAttributes": {
14+
"docs:8000": {
15+
"label": "Docs server",
16+
"protocol": "http",
17+
"onAutoForward": "openBrowser"
18+
}
19+
},
20+
"otherPortsAttributes": {
21+
"onAutoForward": "ignore"
22+
}
23+
}

.env.dist

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,51 @@
1-
###############################
2-
# Docker compose configuration #
3-
###############################
1+
################################
2+
# Docker Compose configuration #
3+
################################
44

5-
# Host system port where the live documentation is to be made accessible
6-
COMPOSE_START_PORT=8000
5+
# Must match Docker Compose project name used to start the other service containers to allow devcontainer
6+
# to communicate with them (setup.sh derives this from the directory basename by default)
7+
COMPOSE_PROJECT_NAME=react-ui
78

8-
# Host system port where Playwright Component Testing report is to be made accessible
9+
# Docker compose ports for Docs server instances
10+
COMPOSE_DOCS_SERVER_PORT=8000
11+
12+
# Docker compose ports for Playwright Component Testing report server
913
COMPOSE_PLAYWRIGHT_REPORT_PORT=9323
1014

15+
# Flag whether the `node` and `docs` service containers should automatically install dependencies,
16+
# build, and run the application (JavaScript files watcher, docs server) when they start
17+
COMPOSE_AUTOSTART=false
18+
1119
# Ownership of the files created in the container
20+
# ⚠️ [Linux] This needs to be set to the output of `id --user`
21+
# ⚠️ [MacOS] This needs to be set to 1000
1222
COMPOSE_UID=1000
23+
# ⚠️ [Linux] This needs to be set to the output of `id --group`
24+
# ⚠️ [MacOS] This needs to be set to 1000
1325
COMPOSE_GID=1000
26+
27+
#############################
28+
# Devcontainer configuration #
29+
#############################
30+
31+
# IDEs automatically mount the host's SSH agent socket into the container
32+
# Visual Studio Code does this by default, it can be disabled by setting the following variable to true.
33+
# JetBrains IDEs do not mount this by default, but they can be configured to do so.
34+
BLOCK_SSH_AUTH_SOCK=false
35+
36+
# Select your preferred editor and visual (vim, nano)
37+
EDITOR=vim
38+
VISUAL=vim
39+
40+
# Select your preferred shell (/bin/bash, /bin/fish, /bin/zsh)
41+
SHELL=/bin/bash
42+
43+
###########################
44+
# Playwright configuration #
45+
###########################
46+
47+
# Number of workers to use to run Playwright tests
48+
PW_WORKERS=1
49+
50+
# Port used by Playwright Component Testing to serve the test files
51+
PW_CT_PORT=3100

.env.playwright.dist

Lines changed: 0 additions & 9 deletions
This file was deleted.

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
/coverage
2+
/docker-compose.yml
3+
/docker/react_ui_devcontainer_local
4+
!/docker/react_ui_devcontainer_local/Dockerfile.dist
25
/dist
36
/node_modules
47
/playwright-report/
58
/site
69
/src/docs/_assets/generated/*
710
/tests/playwright/.temp/
811
.env
9-
.env.playwright
1012
statistics.html
1113
!.gitkeep

CLAUDE.md

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,10 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
44

55
## Commands
66

7-
All `npm` commands must be run inside Docker containers. Use `node_shell` for most tasks, `playwright` for visual tests.
7+
All commands below are meant to be run directly inside the Docker container `devcontainer`.
8+
If you open the project in a Dev Container, you can run these commands without manually
9+
starting Docker Compose on the host.
810

9-
```bash
10-
# Enter node_shell container
11-
docker compose run --rm node_shell
12-
13-
# Enter playwright container (for visual tests)
14-
docker compose run --rm --service-ports playwright
15-
```
16-
17-
**Within `node_shell`:**
1811

1912
```bash
2013
npm run lint # All linters (ESLint + Stylelint + Markdownlint)
@@ -23,11 +16,6 @@ npm run stylelint # SCSS linting
2316
npm run test:jest # All Jest unit tests
2417
npm run test:jest:ts -- <file> # Single TypeScript test file
2518
npm run test:jest:js -- <file> # Single JavaScript test file
26-
```
27-
28-
**Within `playwright`:**
29-
30-
```bash
3119
npm run test:playwright-ct:all # All component tests
3220
npm run test:playwright-ct:all-with-update # Update snapshots
3321
npm run test:playwright-ct:all -- -- src/components/Button # Tests for one component

docker-compose.base.yml

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
services:
2+
# This service is responsible for providing the main development environment for developers
3+
devcontainer:
4+
hostname: ${COMPOSE_PROJECT_NAME:-react-ui}_devcontainer
5+
build:
6+
context: docker/react_ui_devcontainer/
7+
dockerfile: Dockerfile
8+
# Start dependent services before starting the `devcontainer` service to ensure that the necessary environments
9+
# and tools are available when the `devcontainer` starts.
10+
depends_on:
11+
node:
12+
condition: service_started
13+
playwright:
14+
condition: service_started
15+
docs:
16+
condition: service_started
17+
# Run as host UID/GID so files created in mounted volumes are owned correctly on the host.
18+
# The images use `fixuid` (https://github.com/boxboat/fixuid) to remap the built-in `developer`
19+
# user to these IDs at startup — the `user:` directive is required for that remap to work.
20+
# Applied to all services below for the same reason.
21+
user: ${COMPOSE_UID}:${COMPOSE_GID}
22+
# Keep the container running indefinitely to allow developers to attach to it and use it as their development environment
23+
command: sleep infinity
24+
# Injects environment variables from the `.env` file into the `devcontainer` service,
25+
# making them accessible within the container's environment.
26+
env_file:
27+
- .env
28+
environment:
29+
# This must be set correctly for the `devcontainer` to be able to access the host's Docker daemon,
30+
# enabling Docker-from-Docker capabilities (e.g., running Docker commands from within the `devcontainer`).
31+
COMPOSE_PROJECT_NAME: ${COMPOSE_PROJECT_NAME:-react-ui}
32+
init: true
33+
volumes:
34+
- .:/workspace:z
35+
# The following volume is used to allow the `devcontainer` to access the host's Docker daemon,
36+
# enabling Docker-from-Docker capabilities (e.g., running Docker commands from within the `devcontainer`).
37+
- /var/run/docker.sock:/var/run/docker.sock
38+
# The following named volumes persist data (e.g. terminal history, AI tools data, etc.) across container restarts.
39+
# Using separate named volumes (instead of a single volume with subpaths) allows Docker to automatically
40+
# seed the volume with data from the image on first use.
41+
- terminal-history:/home/developer/.terminal_history
42+
- claude-config:/home/developer/.config/claude
43+
- claude-state:/home/developer/.local/state/claude
44+
- copilot:/home/developer/.copilot
45+
- copilot-config:/home/developer/.config/copilot
46+
- opencode-config:/home/developer/.config/opencode
47+
- opencode-share:/home/developer/.local/share/opencode
48+
- opencode-state:/home/developer/.local/state/opencode
49+
50+
# This service provides Node environment and NPM
51+
node:
52+
build: docker/node
53+
user: ${COMPOSE_UID}:${COMPOSE_GID}
54+
entrypoint: sh -c 'if [ "$$COMPOSE_AUTOSTART" = "true" ]; then sh scripts/auto-start-node.sh; else sleep infinity; fi'
55+
env_file:
56+
- .env
57+
volumes:
58+
- .:/workspace:z
59+
60+
# This service provides Playwright environment and tools for browser automation and testing
61+
playwright:
62+
build: docker/playwright
63+
user: ${COMPOSE_UID}:${COMPOSE_GID}
64+
command: sleep infinity
65+
env_file:
66+
- .env
67+
ports:
68+
- ${COMPOSE_PLAYWRIGHT_REPORT_PORT}:9323
69+
volumes:
70+
- .:/workspace:z
71+
72+
# This provides server for documentation
73+
docs:
74+
build: docker/mkdocs
75+
user: ${COMPOSE_UID}:${COMPOSE_GID}
76+
entrypoint: sh -c 'if [ "$$COMPOSE_AUTOSTART" = "true" ]; then sh scripts/auto-start-mkdocs.sh; else sleep infinity; fi'
77+
env_file:
78+
- .env
79+
ports:
80+
- ${COMPOSE_DOCS_SERVER_PORT}:8000
81+
volumes:
82+
- .:/workspace:z
83+
84+
volumes:
85+
# The following volumes are used to persist data (e.g. terminal history, AI tools data, etc.) across container restarts
86+
terminal-history:
87+
claude-config:
88+
claude-state:
89+
copilot:
90+
copilot-config:
91+
opencode-config:
92+
opencode-share:
93+
opencode-state:

docker-compose.yml

Lines changed: 0 additions & 43 deletions
This file was deleted.

docker-compose.yml.dist

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
services:
2+
# This service is responsible for providing the main development environment for developers
3+
devcontainer:
4+
extends:
5+
file: docker-compose.base.yml
6+
service: devcontainer
7+
# Use `build` when you want to customize the devcontainer using `docker/react_ui_devcontainer_local/Dockerfile`
8+
# build:
9+
# context: ./docker/react_ui_devcontainer_local/
10+
# dockerfile: Dockerfile
11+
# Use `image` when you want to use the default devcontainer
12+
image: react-ui_devcontainer
13+
14+
# This service provides Node environment and NPM
15+
node:
16+
extends:
17+
file: docker-compose.base.yml
18+
service: node
19+
20+
# This service provides Playwright environment and tools for browser automation and testing
21+
playwright:
22+
extends:
23+
file: docker-compose.base.yml
24+
service: playwright
25+
26+
# This provides server for documentation
27+
docs:
28+
extends:
29+
file: docker-compose.base.yml
30+
service: docs
31+
32+
volumes:
33+
# The following volumes are used to persist data (e.g. terminal history, AI tools data, etc.) across container restarts
34+
terminal-history:
35+
claude-config:
36+
claude-state:
37+
copilot:
38+
copilot-config:
39+
opencode-config:
40+
opencode-share:
41+
opencode-state:

docker/build-docker-images.sh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/bin/bash
2+
3+
set -e
4+
trap 'echo "Failed to build Docker images"; exit 1' ERR
5+
6+
cd "$(dirname "$0")"
7+
8+
echo "Building Docker images..."
9+
10+
if [ ! -f ../.env ]; then
11+
echo "Error: .env file not found in the project root"
12+
exit 1
13+
fi
14+
15+
PROJECT_NAME=$(grep -E '^COMPOSE_PROJECT_NAME=' ../.env | cut -d '=' -f 2-)
16+
PROJECT_DEVCONTAINER_IMAGE="${PROJECT_NAME}_devcontainer"
17+
18+
echo "Building Docker image $PROJECT_DEVCONTAINER_IMAGE..."
19+
docker build -t "$PROJECT_DEVCONTAINER_IMAGE" -f ./react_ui_devcontainer/Dockerfile ./react_ui_devcontainer/
20+
21+
cd ..
22+
23+
echo "Building project Docker images using docker-compose..."
24+
docker compose build
25+
26+
echo "All Docker images built successfully!"

docker/mkdocs/Dockerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1-
FROM squidfunk/mkdocs-material:9
1+
# We freezed the version of mkdocs-material to prevent issue with live reload
2+
# See <https://github.com/squidfunk/mkdocs-material/issues/8478>
3+
FROM squidfunk/mkdocs-material:9.6.20
24
RUN mkdir /workspace
35
WORKDIR /workspace

0 commit comments

Comments
 (0)