-
-
Notifications
You must be signed in to change notification settings - Fork 8.2k
feat: add dev container configuration for development experience #15895
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
djunehor
wants to merge
2
commits into
nestjs:master
Choose a base branch
from
djunehor:feat/devcontainer-support
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+582
−1
Open
Changes from 1 commit
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| # Use official VS Code devcontainer Node.js image as base (updated to Node 20 for NestJS requirements) | ||
| FROM mcr.microsoft.com/vscode/devcontainers/typescript-node:20-bullseye | ||
|
|
||
| # Install system dependencies and development tools | ||
| RUN apt-get update && apt-get install -y \ | ||
| # Build tools for native dependencies | ||
| build-essential \ | ||
| python3 \ | ||
| python3-pip \ | ||
| # Git for version control | ||
| git \ | ||
| # Utilities | ||
| curl \ | ||
| wget \ | ||
| vim \ | ||
| nano \ | ||
| jq \ | ||
| sudo \ | ||
| # Docker CLI for integration tests | ||
| ca-certificates \ | ||
| gnupg \ | ||
| lsb-release \ | ||
| # Clean up | ||
| && rm -rf /var/lib/apt/lists/* | ||
|
|
||
| # Install Docker CLI | ||
| RUN curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg \ | ||
| && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null \ | ||
| && apt-get update \ | ||
| && apt-get install -y docker-ce-cli docker-compose-plugin \ | ||
| && rm -rf /var/lib/apt/lists/* | ||
|
|
||
| # Install global npm packages for development | ||
| RUN npm install -g \ | ||
| # TypeScript tooling | ||
| typescript \ | ||
| ts-node \ | ||
| nodemon \ | ||
| # Testing tools | ||
| mocha \ | ||
| nyc \ | ||
| # Linting and formatting | ||
| eslint \ | ||
| prettier \ | ||
| # Development utilities | ||
| concurrently \ | ||
| cross-env \ | ||
| # Package management | ||
| lerna \ | ||
| # Build tools | ||
| gulp-cli | ||
|
|
||
| # Set npm configuration for NestJS | ||
| RUN npm config set legacy-peer-deps true | ||
|
|
||
| # Create non-root user with proper permissions | ||
| ARG USERNAME=node | ||
| ARG USER_UID=1000 | ||
| ARG USER_GID=$USER_UID | ||
|
|
||
| # Ensure node user has the correct UID/GID | ||
| RUN groupmod --gid $USER_GID $USERNAME \ | ||
| && usermod --uid $USER_UID --gid $USER_GID $USERNAME \ | ||
| && chown -R $USER_UID:$USER_GID /home/$USERNAME | ||
|
|
||
| # Add node user to docker group for Docker socket access | ||
| RUN groupadd docker || true \ | ||
| && usermod -aG docker $USERNAME \ | ||
| && echo "$USERNAME ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers | ||
|
|
||
| # Set working directory | ||
| WORKDIR /workspace | ||
|
|
||
| # Create node_modules directory with proper permissions as root | ||
| RUN mkdir -p /workspace/node_modules \ | ||
| && chown -R $USER_UID:$USER_GID /workspace | ||
|
|
||
| # Switch to node user for development | ||
| USER $USERNAME | ||
|
|
||
| # Create directories for development (will be done by post-create script) | ||
| RUN mkdir -p /home/$USERNAME/.vscode-server | ||
|
|
||
| # Default command (will be overridden by docker-compose) | ||
| CMD ["bash"] | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,138 @@ | ||
| # NestJS Development Container | ||
|
|
||
| This development container provides a complete, pre-configured environment for NestJS development with all necessary dependencies, services, and VS Code extensions. | ||
|
|
||
| ## What's Included | ||
|
|
||
| ### Development Environment | ||
| - **Node.js 20 LTS** with npm configured for legacy peer dependencies (meets requirement >= 10.13.0) | ||
| - **TypeScript** and related development tools | ||
| - **Docker CLI** for containerized services | ||
| - **GitHub CLI** for seamless GitHub integration | ||
|
|
||
| ### VS Code Extensions | ||
| - TypeScript and JavaScript language support | ||
| - Code formatting with Prettier | ||
| - Linting with ESLint | ||
| - Testing integration with Mocha | ||
| - Docker support for container management | ||
| - Git enhancement with GitLens | ||
| - Markdown support for documentation | ||
|
|
||
| ### Integration Services | ||
| - **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 | ||
|
|
||
| ## 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. | ||
|
|
||
| ## Available Commands | ||
|
|
||
| ### Build and Test | ||
| ```bash | ||
| npm run build # Build all packages | ||
| npm run build:prod # Build packages near source files | ||
| npm test # Run unit tests | ||
| npm run test:integration # Run integration tests | ||
| npm run lint # Run ESLint | ||
| npm run format # Format code with Prettier | ||
| ``` | ||
|
|
||
| ### Development | ||
| ```bash | ||
| npm run prepare # Setup development environment | ||
| sh scripts/prepare.sh # Alternative: run prepare script directly | ||
| npm start # Start sample application | ||
| ``` | ||
|
|
||
| ### Services | ||
| ```bash | ||
| npm run test:docker:up # Start integration services | ||
| npm run test:docker:down # Stop integration services | ||
| ``` | ||
|
|
||
| ### Integration Testing | ||
| ```bash | ||
| npm run test:integration # Run integration tests | ||
| sh scripts/run-integration.sh # Alternative: run integration script directly | ||
| ``` | ||
|
|
||
| ## 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 | ||
|
|
||
| ## Troubleshooting | ||
|
|
||
| ### Permission Issues | ||
| If you encounter permission issues: | ||
| ```bash | ||
| sudo chown -R node:node /workspace | ||
| ``` | ||
|
|
||
| ### Missing Dependencies | ||
| If dependencies are missing: | ||
| ```bash | ||
| npm install --legacy-peer-deps | ||
| ``` | ||
|
|
||
| ### Services Not Starting | ||
| To manually start integration services: | ||
| ```bash | ||
| npm run test:docker:up | ||
| ``` | ||
|
|
||
| ### Container Creation Issues | ||
| If you see errors about mounting files or directories, this usually means: | ||
| 1. A file/directory referenced in docker-compose.yml doesn't exist | ||
| 2. VS Code may be trying to mount a non-existent configuration file | ||
|
|
||
| To fix: | ||
| 1. Check that all referenced files exist | ||
| 2. Rebuild the devcontainer: `Ctrl+Shift+P` → "Dev Containers: Rebuild Container" | ||
|
|
||
| ## Container Configuration | ||
|
|
||
| - **Base Image**: `mcr.microsoft.com/vscode/devcontainers/typescript-node:20-bullseye` | ||
| - **User**: `node` (UID 1000) | ||
| - **Workspace**: `/workspace` | ||
| - **Docker**: Docker-in-Docker enabled for integration testing | ||
|
|
||
| ## Contributing | ||
|
|
||
| This devcontainer is designed to provide a consistent development environment for all contributors. If you need additional tools or services, please update the configuration files and test thoroughly before submitting changes. | ||
|
|
||
| ### Testing the DevContainer | ||
|
|
||
| To validate that the devcontainer works correctly, you can run: | ||
|
|
||
| ```bash | ||
| # Quick smoke test (2-3 minutes) | ||
| ./.devcontainer/smoke-test.sh | ||
|
|
||
| # Full validation test (5-10 minutes) | ||
| ./.devcontainer/validate-devcontainer.sh | ||
| ``` | ||
|
|
||
| These tests verify: | ||
| - ✅ Node.js, npm, and TypeScript are working | ||
| - ✅ Package installation and building | ||
| - ✅ Docker services are running | ||
| - ✅ Unit tests can execute | ||
| - ✅ Code quality tools (ESLint, Prettier) are functional | ||
| - ✅ Integration test setup is ready | ||
|
|
||
| For more information about contributing to NestJS, see [CONTRIBUTING.md](../CONTRIBUTING.md). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,166 @@ | ||
| { | ||
| "name": "NestJS Development Environment", | ||
| "dockerComposeFile": ["docker-compose.yml"], | ||
| "service": "devcontainer", | ||
| "workspaceFolder": "/workspace", | ||
| "remoteUser": "node", | ||
| "updateRemoteUserUID": true, | ||
|
|
||
| "customizations": { | ||
| "vscode": { | ||
| "extensions": [ | ||
| "ms-vscode.vscode-typescript-next", | ||
| "ms-vscode.vscode-json", | ||
| "esbenp.prettier-vscode", | ||
| "dbaeumer.vscode-eslint", | ||
| "ms-vscode.vscode-npm-script", | ||
| "christian-kohler.npm-intellisense", | ||
| "leizongmin.node-module-intellisense", | ||
| "christian-kohler.path-intellisense", | ||
| "formulahendry.auto-rename-tag", | ||
| "bradlc.vscode-tailwindcss", | ||
| "hbenl.vscode-test-explorer", | ||
| "hbenl.vscode-mocha-test-adapter", | ||
| "ms-azuretools.vscode-docker", | ||
| "eamodio.gitlens", | ||
| "yzhang.markdown-all-in-one" | ||
| ], | ||
|
|
||
| "settings": { | ||
| "typescript.updateImportsOnFileMove.enabled": "always", | ||
| "typescript.preferences.importModuleSpecifier": "relative", | ||
| "typescript.suggest.autoImports": true, | ||
| "typescript.suggest.completeFunctionCalls": true, | ||
| "typescript.workspaceSymbols.scope": "allOpenProjects", | ||
|
|
||
| "editor.rulers": [100], | ||
| "editor.tabSize": 2, | ||
| "editor.insertSpaces": true, | ||
| "editor.detectIndentation": false, | ||
| "editor.formatOnSave": true, | ||
| "editor.formatOnPaste": true, | ||
| "editor.codeActionsOnSave": { | ||
| "source.fixAll.eslint": "explicit", | ||
| "source.organizeImports": "explicit" | ||
| }, | ||
|
|
||
| "prettier.configPath": ".prettierrc", | ||
| "prettier.ignorePath": ".prettierignore", | ||
| "prettier.requireConfig": true, | ||
|
|
||
| "eslint.workingDirectories": [ | ||
| "./packages", | ||
| "./integration", | ||
| "./sample" | ||
| ], | ||
| "eslint.validate": ["javascript", "typescript"], | ||
|
|
||
| "files.exclude": { | ||
| "**/node_modules": true, | ||
| "**/dist": true, | ||
| "**/.nyc_output": true, | ||
| "**/coverage": true | ||
| }, | ||
| "search.exclude": { | ||
| "**/node_modules": true, | ||
| "**/dist": true, | ||
| "**/.nyc_output": true, | ||
| "**/coverage": true | ||
| }, | ||
|
|
||
| "docker.composeCommand": "docker-compose", | ||
| "docker.dockerComposeDetached": true, | ||
| "docker.environment": {}, | ||
| "docker.dockerPath": "docker", | ||
| "docker.explorerRefreshInterval": 2000, | ||
| "docker.showExplorer": false, | ||
|
|
||
| "terminal.integrated.defaultProfile.linux": "bash", | ||
| "terminal.integrated.env.linux": { | ||
| "NODE_ENV": "development" | ||
| }, | ||
|
|
||
| "mochaExplorer.files": [ | ||
| "packages/**/*.spec.ts", | ||
| "integration/**/*.spec.ts" | ||
| ], | ||
| "mochaExplorer.env": { | ||
| "NODE_ENV": "test" | ||
| }, | ||
|
|
||
| "git.confirmSync": false, | ||
| "git.enableSmartCommit": true, | ||
| "git.autofetch": true, | ||
|
|
||
| "npm.enableRunFromFolder": true, | ||
| "npm.packageManager": "npm", | ||
| "emmet.includeLanguages": { | ||
| "typescript": "html", | ||
| "javascript": "html" | ||
| } | ||
| } | ||
| } | ||
| }, | ||
|
|
||
| "forwardPorts": [ | ||
| 3000, 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010, 8080, | ||
| 8081, 8082, 14223, 16222, 18222, 16379, 11883, 19001, 13306 | ||
| ], | ||
|
|
||
| "portsAttributes": { | ||
| "3000": { | ||
| "label": "Main Application", | ||
| "onAutoForward": "notify" | ||
| }, | ||
| "14223": { | ||
| "label": "NATS", | ||
| "onAutoForward": "silent" | ||
| }, | ||
| "16222": { | ||
| "label": "NATS Cluster", | ||
| "onAutoForward": "silent" | ||
| }, | ||
| "18222": { | ||
| "label": "NATS HTTP", | ||
| "onAutoForward": "silent" | ||
| }, | ||
| "16379": { | ||
| "label": "Redis", | ||
| "onAutoForward": "silent" | ||
| }, | ||
| "11883": { | ||
| "label": "MQTT", | ||
| "onAutoForward": "silent" | ||
| }, | ||
| "19001": { | ||
| "label": "MQTT WebSocket", | ||
| "onAutoForward": "silent" | ||
| }, | ||
| "13306": { | ||
| "label": "MySQL", | ||
| "onAutoForward": "silent" | ||
| } | ||
| }, | ||
|
|
||
| "postCreateCommand": "bash .devcontainer/scripts/post-create.sh", | ||
|
|
||
| "features": { | ||
| "ghcr.io/devcontainers/features/docker-in-docker:2": { | ||
| "version": "latest", | ||
| "enableNonRootDocker": "true" | ||
| }, | ||
| "ghcr.io/devcontainers/features/github-cli:1": { | ||
| "version": "latest" | ||
| } | ||
| }, | ||
|
|
||
| "mounts": [ | ||
| "source=/var/run/docker.sock,target=/var/run/docker-host.sock,type=bind" | ||
| ], | ||
|
|
||
| "containerEnv": { | ||
| "NODE_ENV": "development", | ||
| "npm_config_legacy_peer_deps": "true", | ||
| "DOCKER_HOST": "unix:///var/run/docker-host.sock" | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we really need some of these packages to be installed globally?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah i'd say the fewer global deps the better
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.