I am really close on this.. but can't seem to get it to load the nodejs project.
The Docker log:
2025-03-24 09:16:56 Container started
2025-03-24 09:16:57 node:internal/modules/cjs/loader:1143
2025-03-24 09:16:57 throw err;
2025-03-24 09:16:57 ^
2025-03-24 09:16:57
2025-03-24 09:16:57 Error: Cannot find module 'express'
2025-03-24 09:16:57 Require stack:
2025-03-24 09:16:57 - /workspace/index.js
2025-03-24 09:16:57 at Module._resolveFilename (node:internal/modules/cjs/loader:1140:15)
2025-03-24 09:16:57 at Module._load (node:internal/modules/cjs/loader:981:27)
2025-03-24 09:16:57 at Module.require (node:internal/modules/cjs/loader:1231:19)
2025-03-24 09:16:57 at require (node:internal/modules/helpers:177:18)
2025-03-24 09:16:57 at Object.<anonymous> (/workspace/index.js:1:17)
2025-03-24 09:16:57 at Module._compile (node:internal/modules/cjs/loader:1364:14)
2025-03-24 09:16:57 at Module._extensions..js (node:internal/modules/cjs/loader:1422:10)
2025-03-24 09:16:57 at Module.load (node:internal/modules/cjs/loader:1203:32)
2025-03-24 09:16:57 at Module._load (node:internal/modules/cjs/loader:1019:12)
2025-03-24 09:16:57 at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:128:12) {
2025-03-24 09:16:57 code: 'MODULE_NOT_FOUND',
2025-03-24 09:16:57 requireStack: [ '/workspace/index.js' ]
2025-03-24 09:16:57 }
2025-03-24 09:16:57
2025-03-24 09:16:57 Node.js v18.20.7
Background
I am on a mac, using the latest version of docker desktop and the latest version of VS Code
Docker desktop Bind Mounts
It appears as if Docker Desktop is binding the correct directory to the workspace folder in the container:
Project structure
The Project has the following structure:
/RP_server
|-- .devcontainer/
| |-- devcontainer.json
| |-- docker-compose.yml
|-- nodejs-service/
| |-- Dockerfile
| |-- package.json
| |-- index.js
| |-- swagger.json
|-- python-service/
| |-- Dockerfile
| |-- main.py
| |-- requirements.txt
| |-- swagger.yaml
File contents
devcontainer.json
{
"name": "Multi-Container Dev Environment",
"dockerComposeFile": "./docker-compose.yml",
"service": "nodejs-service",
"workspaceFolder": "/workspace",
"customizations": {
"vscode": {
"extensions": [
"dbaeumer.vscode-eslint",
"ms-python.python",
"ms-azuretools.vscode-docker"
],
"settings": {}
}
}
}
docker-compose.yml
services:
postgres:
image: postgres:15
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: mydb
ports:
- '5432:5432'
volumes:
- postgres-data:/var/lib/postgresql/data
nodejs-service:
build:
context: ../nodejs-service
ports:
- '3000:3000'
volumes:
- ../nodejs-service:/workspace
depends_on:
- postgres
python-service:
build:
context: ../python-service
ports:
- '8000:8000'
volumes:
- ../python-service:/workspace
depends_on:
- postgres
volumes:
postgres-data:
nodejs-service/Dockerfile
FROM node:18
WORKDIR /workspace
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "index.js"]
nodejs-service/package.json
{
"name": "nodejs-service",
"version": "1.0.0",
"description": "Node.js service",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"express": "^4.18.2",
"swagger-jsdoc": "^6.2.8",
"swagger-ui-express": "^4.6.2"
}
}
nodejs-service/index.js
const express = require('express');
const swaggerUi = require('swagger-ui-express');
const swaggerDocument = require('./swagger.json');
const app = express();
const PORT = 3000;
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
app.get('/', (req, res) => {
res.json({ message: 'Hello from Node.js Service!' });
});
app.listen(PORT, () => {
console.log(`Node.js service running on http://localhost:${PORT}`);
});
nodejs-service/swagger.json
{
"swagger": "2.0",
"info": {
"version": "1.0.0",
"title": "Node.js Service API",
"description": "API documentation for Node.js Service"
},
"host": "localhost:3000",
"basePath": "/",
"schemes": [
"http"
],
"paths": {
"/": {
"get": {
"summary": "Say Hello",
"responses": {
"200": {
"description": "Successful response",
"schema": {
"type": "object",
"properties": {
"message": {
"type": "string"
}
}
}
}
}
}
}
}
}
python-service/Dockerfile
FROM python:3.10
WORKDIR /workspace
COPY requirements.txt ./
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["python", "main.py"]
python-service/main.py
from fastapi import FastAPI
from fastapi.openapi.utils import get_openapi
from fastapi.responses import JSONResponse
app = FastAPI(docs_url="/api-docs")
@app.get("/")
async def read_root():
return JSONResponse({"message": "Hello from Python Service!"})
def custom_openapi():
if app.openapi_schema:
return app.openapi_schema
openapi_schema = get_openapi(
title="Python Service API",
version="1.0.0",
description="API documentation for Python Service",
routes=app.routes,
)
app.openapi_schema = openapi_schema
return app.openapi_schema
app.openapi = custom_openapi
python-service/requirements.txt
fastapi
uvicorn
pyyaml
python-service/swagger.yml
openapi: 3.0.0
info:
title: Python Service API
version: 1.0.0
paths:
/:
get:
summary: Say Hello
responses:
200:
description: Successful response
content:
application/json:
schema:
type: object
properties:
message:
type: string