feat: add dev container configuration for development experience#15895
feat: add dev container configuration for development experience#15895djunehor wants to merge 2 commits intonestjs:masterfrom
Conversation
Adds comprehensive VS Code dev container configuration to enable one-click development environment setup. The devcontainer includes Node.js 20 LTS, TypeScript tooling, and essential development services (Redis, NATS, MySQL) with pre-configured VS Code extensions and settings. Closes nestjs#15864
Pull Request Test Coverage Report for Build a79e1bef-a856-4cb1-8b31-900ac30e3cbfDetails
💛 - Coveralls |
.devcontainer/Dockerfile
Outdated
| nodemon \ | ||
| # Testing tools | ||
| mocha \ | ||
| nyc \ |
There was a problem hiding this comment.
do we really need some of these packages to be installed globally?
There was a problem hiding this comment.
You're right - these don't need to be global. They're already in devDependencies and can be accessed via npm scripts or npx. I'll update the Dockerfile to remove the global installations of mocha, nyc, nodemon, ts-node, and other dev tools.
The only global package that might be justified is npm-check-updates for convenience, but I can remove that too if you prefer. Would you like me to keep just the base Node image and rely entirely on the local node_modules?
There was a problem hiding this comment.
yeah i'd say the fewer global deps the better
There was a problem hiding this comment.
Done! I've removed all global npm package installations from the Dockerfile. The devcontainer now relies entirely on local node_modules - all tools (typescript, ts-node, mocha, nyc, eslint, prettier, concurrently, cross-env, lerna, gulp-cli) are accessible via npx or npm scripts.
Removed global npm package installations (typescript, ts-node, mocha, nyc, eslint, prettier, concurrently, cross-env, lerna, gulp-cli) from the devcontainer Dockerfile. These packages are already available in devDependencies and can be accessed via npm scripts or npx, eliminating the need for global installations. This change aligns with the principle of minimizing global dependencies and relying on local node_modules instead.
There was a problem hiding this comment.
Pull request overview
This PR adds comprehensive VS Code dev container configuration to enable one-click development environment setup for NestJS contributors. The devcontainer provides Node.js 20 LTS, essential development services, and pre-configured VS Code extensions to simplify onboarding and ensure environment consistency.
Changes:
- Adds complete devcontainer configuration with Dockerfile, docker-compose setup, and lifecycle scripts
- Configures development services (Redis, NATS, MySQL) in isolated containers
- Includes 15+ VS Code extensions and optimized editor settings for TypeScript/NestJS development
- Updates .gitignore to allow .devcontainer directory in version control
Reviewed changes
Copilot reviewed 6 out of 7 changed files in this pull request and generated 25 comments.
Show a summary per file
| File | Description |
|---|---|
| .gitignore | Removes .devcontainer from ignore list to include devcontainer config in repo |
| .devcontainer/devcontainer.json | Main configuration for VS Code devcontainer with extensions, settings, ports, and lifecycle hooks |
| .devcontainer/Dockerfile | Custom image based on Node 20 with build tools, Docker CLI, and proper user permissions |
| .devcontainer/docker-compose.yml | Service definitions for Redis, NATS, and MySQL development dependencies |
| .devcontainer/scripts/post-create.sh | Post-creation script for dependency installation and workspace setup |
| .devcontainer/scripts/post-start.sh | Post-start script for service health checks |
| .devcontainer/README.md | Comprehensive documentation for devcontainer usage and troubleshooting |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| environment: | ||
| MYSQL_ROOT_PASSWORD: root | ||
| MYSQL_DATABASE: test | ||
| MYSQL_USER: nestjs | ||
| MYSQL_PASSWORD: nestjs |
There was a problem hiding this comment.
The MySQL container creates both a root user (MYSQL_ROOT_PASSWORD: root) and a dedicated user (MYSQL_USER: nestjs, MYSQL_PASSWORD: nestjs), but the devcontainer documentation doesn't explain which credentials should be used for connecting to MySQL. Applications need to know which user/password to use for database connections. Add documentation specifying the recommended MySQL connection credentials.
| ## What's Included | ||
|
|
||
| ### Development Environment | ||
| - **Node.js 20 LTS** with npm configured for legacy peer dependencies (meets requirement >= 10.13.0) |
There was a problem hiding this comment.
The documentation incorrectly states the Node.js requirement is ">= 10.13.0", but according to the package.json in the repository, the actual engine requirement is "node": ">= 20". The comment should reflect the accurate requirement of Node.js 20 or higher.
| - **Node.js 20 LTS** with npm configured for legacy peer dependencies (meets requirement >= 10.13.0) | |
| - **Node.js 20 LTS** with npm configured for legacy peer dependencies (requires Node.js >= 20) |
| # NATS for messaging | ||
| nats: | ||
| container_name: nestjs-dev-nats | ||
| image: nats:2.10-alpine |
There was a problem hiding this comment.
The NATS container uses a specific pinned version (nats:2.10-alpine) while the integration test docker-compose.yml uses the 'nats' image without a version tag (which defaults to 'latest'). This version mismatch could lead to inconsistencies between devcontainer development and integration test environments. Consider using the same NATS image version as integration tests or documenting why different versions are used.
| image: nats:2.10-alpine | |
| image: nats |
| "mounts": [ | ||
| "source=/var/run/docker.sock,target=/var/run/docker-host.sock,type=bind" | ||
| ], | ||
|
|
There was a problem hiding this comment.
Docker socket is mounted twice with different configurations. In devcontainer.json line 158, it's mounted via the "mounts" property, and in docker-compose.yml line 8, it's mounted via the volumes property. While this might work, it's redundant and could cause confusion. The docker-compose.yml mount should be sufficient, so consider removing the duplicate mount specification in devcontainer.json.
| "mounts": [ | |
| "source=/var/run/docker.sock,target=/var/run/docker-host.sock,type=bind" | |
| ], |
| && usermod -aG docker $USERNAME \ | ||
| && echo "$USERNAME ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers |
There was a problem hiding this comment.
The Dockerfile grants passwordless sudo access to the node user with "NOPASSWD:ALL" which is a security risk. While this is for a development environment, it's still a bad security practice that could be exploited if the container is exposed or if malicious code is run. Consider either removing sudo access entirely if not needed, or requiring a password, or limiting sudo access to specific commands that are actually needed.
| && usermod -aG docker $USERNAME \ | |
| && echo "$USERNAME ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers | |
| && usermod -aG docker $USERNAME |
| - **MQTT/Mosquitto** (ports 11883, 19001) - IoT messaging with WebSocket support | ||
|
|
||
| ## Getting Started | ||
|
|
||
| 1. **Open in Dev Container**: VS Code will prompt to reopen in container when opening this repository | ||
| 2. **Wait for Setup**: The container will automatically install dependencies and build packages | ||
| 3. **Services will start automatically**: Integration services (Redis, NATS, etc.) start during setup | ||
| 4. **Start Development**: All services will be available and ready for development | ||
|
|
||
| **Note**: Integration services start after the main container is ready, not during container creation. This ensures reliable startup. |
There was a problem hiding this comment.
Documentation states "Services will start automatically" but this contradicts the actual implementation and the PR description. According to the docker-compose.yml, only Redis, NATS, and MySQL services are defined, not MQTT/Mosquitto or PostgreSQL which are mentioned in the README. Additionally, the post-create.sh script explicitly notes that integration services are NOT started automatically (lines 64-69).
| - **MQTT/Mosquitto** (ports 11883, 19001) - IoT messaging with WebSocket support | |
| ## Getting Started | |
| 1. **Open in Dev Container**: VS Code will prompt to reopen in container when opening this repository | |
| 2. **Wait for Setup**: The container will automatically install dependencies and build packages | |
| 3. **Services will start automatically**: Integration services (Redis, NATS, etc.) start during setup | |
| 4. **Start Development**: All services will be available and ready for development | |
| **Note**: Integration services start after the main container is ready, not during container creation. This ensures reliable startup. | |
| ## Getting Started | |
| 1. **Open in Dev Container**: VS Code will prompt to reopen in container when opening this repository | |
| 2. **Wait for Setup**: The container will automatically install dependencies and build packages | |
| 3. **Start integration services**: Start integration services (Redis, NATS, MySQL, etc.) manually (for example, using Docker Compose) after setup completes | |
| 4. **Start Development**: After integration services are running, they will be available and ready for development | |
| **Note**: Integration services are not started automatically. Start them manually after the main container is ready to ensure reliable startup. |
| - **Redis** (port 16379) - Caching and session storage | ||
| - **NATS** (ports 14223, 16222, 18222) - Message broker with monitoring | ||
| - **MySQL** (port 13306) - Primary database for testing | ||
| - **MQTT/Mosquitto** (ports 11883, 19001) - IoT messaging with WebSocket support |
There was a problem hiding this comment.
The README documents MQTT/Mosquitto services (ports 11883, 19001) and PostgreSQL (port 5432), but these services are not defined in docker-compose.yml. Only Redis, NATS, and MySQL are actually configured. Either add these services to docker-compose.yml or remove them from the documentation.
| - **MQTT/Mosquitto** (ports 11883, 19001) - IoT messaging with WebSocket support |
| "leizongmin.node-module-intellisense", | ||
| "christian-kohler.path-intellisense", | ||
| "formulahendry.auto-rename-tag", | ||
| "bradlc.vscode-tailwindcss", |
There was a problem hiding this comment.
The devcontainer includes the TailwindCSS extension (bradlc.vscode-tailwindcss) which is not relevant to NestJS backend development. NestJS is a backend framework and doesn't use TailwindCSS (which is a CSS framework for frontend). This extension should be removed to keep the devcontainer focused on relevant tools.
| "bradlc.vscode-tailwindcss", |
| # Run the prepare script to set up packages and samples | ||
| if [ -f "scripts/prepare.sh" ]; then | ||
| echo "Running prepare script..." | ||
| # bash scripts/prepare.sh | ||
| echo "Prepare script execution commented out for debugging" | ||
| else | ||
| echo "Warning: Prepare script not found, running manual setup..." | ||
|
|
||
| # Build packages | ||
| # npm run build | ||
| echo "Manual build commented out for debugging" | ||
|
|
||
| # Integration services are not started automatically to ensure robust devcontainer setup. | ||
| echo "" | ||
| echo "Integration services are NOT started automatically." | ||
| echo "If you need integration services for testing, run:" | ||
| echo " npm run test:docker:up" | ||
| echo "from the workspace root after the container starts." | ||
| fi |
There was a problem hiding this comment.
The logic checks if 'scripts/prepare.sh' exists and then comments out its execution, but then provides fallback logic (lines 58-70) that assumes it doesn't exist. This creates confusing control flow. If the prepare script exists (which it does in the repository), the first branch executes but does nothing useful. Either execute the prepare script when it exists, or restructure the logic to clearly indicate what should happen in each case.
| ## Port Forwarding | ||
|
|
||
| The following ports are automatically forwarded for easy access: | ||
| - **3000-3010**: Sample applications | ||
| - **8080-8082**: Additional development servers | ||
| - **16379**: Redis | ||
| - **14223, 16222, 18222**: NATS services | ||
| - **11883, 19001**: MQTT services | ||
| - **13306**: MySQL |
There was a problem hiding this comment.
The devcontainer services are on a separate Docker network ('nestjs-dev') and will be accessible from the devcontainer using their service names (redis, nats, mysql) on their internal ports (6379, 4222, 3306), NOT the host-mapped ports (16379, 14223, 13306). The port forwarding documentation is misleading because it lists the host-mapped ports, but code running inside the devcontainer should connect to the service names with standard ports. The README should clarify: (1) services are accessed via service name with standard ports from inside the container, (2) host-mapped ports are only for accessing services from the host machine.
Adds comprehensive VS Code dev container configuration to enable one-click development environment setup. The devcontainer includes Node.js 20 LTS, TypeScript tooling, and essential development services (Redis, NATS, MySQL) with pre-configured VS Code extensions and settings.
Closes #15864
PR Checklist
Please check if your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
What is the current behavior?
Contributors need to manually set up their local development environment, including Node.js version, dependencies, services (Redis, NATS, MySQL), and VS Code extensions/settings. This creates friction for new contributors and can lead to inconsistent development environments.
Issue Number: #15864
What is the new behavior?
Contributors can now use VS Code's "Reopen in Container" feature to automatically set up a complete, consistent development environment with:
.devcontainer/README.mdDoes this PR introduce a breaking change?
Other information
The devcontainer configuration is purely additive and doesn't affect existing development workflows. Developers can continue using their local setup if preferred. Integration test services are available via
npm run test:docker:upbut are not started automatically to ensure container reliability.The implementation follows VS Code dev container best practices and includes robust error handling for permission issues and npm installation failures that commonly occur in containerized environments.