Skip to content

Instantly share code, notes, and snippets.

@Cozy228
Last active April 9, 2025 06:46
Show Gist options
  • Select an option

  • Save Cozy228/442fe9b5c3d7be26eff2bfe4c94e753c to your computer and use it in GitHub Desktop.

Select an option

Save Cozy228/442fe9b5c3d7be26eff2bfe4c94e753c to your computer and use it in GitHub Desktop.

Backstage Dev Container (Yarn 4, 无 Dockerfile)

本设置包含 Backstage 应用、PostgreSQL 数据库和配置了自签名 SSL 证书的 Nginx 反向代理。使用 Yarn 4 作为包管理器,并且不依赖自定义的 Dockerfile。

1. 初始化步骤 (首次设置需执行)

在启动 Dev Container 之前,请在你的项目根目录下执行以下命令来创建 Nginx 所需的 SSL 证书。

创建证书目录:

# Create the directory structure if it doesn't exist
mkdir -p .devcontainer/nginx/certs

生成自签名证书:

导航到该目录并使用 openssl 生成证书和私钥。

# Navigate into the certificates directory
cd .devcontainer/nginx/certs

# Generate the private key and self-signed certificate (valid for 365 days)
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout nginx.key -out nginx.crt \
  -subj "/C=US/ST=Development/L=DevCity/O=DevOrg/OU=DevDept/CN=localhost"

# Navigate back to the project root directory (optional)
cd ../../..

这将在 .devcontainer/nginx/certs/ 目录下创建 nginx.key (私钥) 和 nginx.crt (证书) 文件。

2. 文件内容

请将以下文件的内容放置在项目对应的路径下。

a) .devcontainer/docker-compose.yml

# .devcontainer/docker-compose.yml
# Defines the services: Backstage app, PostgreSQL database, and Nginx proxy.
version: '3.8'

services:
  # Service for the Backstage application
  app:
    # Use a pre-built Node.js image suitable for Typescript development.
    # Node.js v18+ is recommended for Yarn 4 (Corepack).
    image: mcr.microsoft.com/devcontainers/typescript-node:20 # Or :18, :22 etc.
    container_name: backstage-app-devcontainer

    # Keep the container running idly
    command: sleep infinity

    # Mount the entire project directory into the container's /workspace
    volumes:
      - ..:/workspace:cached

    # Expose Backstage default port and Node debug port
    ports:
      - "7007:7007" # Backstage frontend/backend default port
      - "9229:9229" # Node.js debug port

    # Environment variables needed by Backstage to connect to the database
    # Ensure these align with your Backstage app-config*.yaml files
    environment:
      - POSTGRES_HOST=db
      - POSTGRES_PORT=5432
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres # Use a more secure password if needed
      # Set Backstage base URLs if accessed via Nginx proxy, e.g., https://localhost:8443
      # Adjust according to your Backstage configuration needs:
      # - APP_BASE_URL=https://localhost:8443
      # - BACKEND_BASE_URL=https://localhost:8443/api

    # Ensure the database service is started before the app service
    depends_on:
      - db

    # Run commands as the non-root 'node' user provided by the base image
    user: node

    # Set the default working directory inside the container
    working_dir: /workspace

  # Service for the PostgreSQL database
  db:
    image: postgres:15 # Or your preferred PostgreSQL version
    container_name: postgres-devcontainer
    restart: unless-stopped

    # Mount a Docker volume to persist database data across sessions
    volumes:
      - postgres-data:/var/lib/postgresql/data

    # Environment variables to initialize PostgreSQL
    environment:
      - POSTGRES_DB=backstage_plugin_${USER:-dev} # Example DB name
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres # Should match the 'app' service password

    # Expose port 5432 only within the Docker network by default
    # Uncomment 'ports' mapping if direct access from the host machine is required
    # ports:
    #   - "5432:5432"

  # Service for the Nginx reverse proxy
  nginx:
    image: nginx:latest
    container_name: nginx-devcontainer
    restart: unless-stopped

    # Map host ports to Nginx container ports
    ports:
      - "8443:443" # Host HTTPS port 8443 -> Container port 443
      - "8080:80"  # Host HTTP port 8080 -> Container port 80 (for redirect)

    # Mount Nginx configuration and SSL certificates
    volumes:
      # Custom Nginx configuration file (read-only)
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
      # SSL certificate and key directory (read-only)
      - ./nginx/certs:/etc/nginx/certs:ro

    # Ensure Nginx starts after the application service it proxies to
    depends_on:
      - app

# Define the named volume for PostgreSQL data persistence
volumes:
  postgres-data:

b) .devcontainer/devcontainer.json

// .devcontainer/devcontainer.json
// VS Code Dev Container configuration using Yarn 4
{
  // Name for the Dev Container environment displayed in VS Code
  "name": "Backstage Dev (Yarn 4)",

  // Use Docker Compose to define and manage the services
  "dockerComposeFile": "docker-compose.yml",

  // Specify the primary service VS Code should connect to (the 'app' service)
  "service": "app",

  // Define the workspace folder inside the container where the project is mounted
  "workspaceFolder": "/workspace",

  // --- Features for enhancing the container environment ---
  "features": {
    // Install common utilities like git, curl, etc.
    "ghcr.io/devcontainers/features/common-utils:2": {
      "installZsh": "false", // Do not install zsh unless needed
      "username": "node",    // Configure features for the 'node' user
      "upgradePackages": "true" // Upgrade packages during feature installation
    },
    // Configure Node.js environment, install version 20, and enable Corepack for Yarn 4
    "ghcr.io/devcontainers/features/node:1": {
        "version": "20", // Specify desired Node.js version (>= 18 recommended for corepack)
        "nodeGypDependencies": true, // Install common node-gyp dependencies
        "corepack": "enable" // Automatically enable corepack
    },
    // Include Docker client for interacting with Docker daemon from within the container (optional)
    "ghcr.io/devcontainers/features/docker-in-docker:2": {
       "version": "latest",
       "moby": true // Use Moby (open source Docker) engine
    }
  },

  // --- Port Forwarding: Map container ports to the host machine ---
  "forwardPorts": [
    7007, // Backstage default application port
    8443, // Nginx HTTPS port mapped to host
    8080, // Nginx HTTP port mapped to host (for redirect)
    5432  // Forward PostgreSQL port only if direct access needed from host
  ],

  // --- VS Code Settings: Applied inside the container ---
  "settings": {
    "terminal.integrated.defaultProfile.linux": "bash", // Set default terminal shell

    // Ensure VS Code uses the workspace's version of TypeScript managed by Yarn
    "typescript.tsdk": "/workspace/node_modules/typescript/lib",
    "typescript.enablePromptUseWorkspaceTsdk": true,

    // Improves searching in projects with large node_modules (optional)
    "search.exclude": {
      "**/node_modules": false
    },

    // Example: Configure ESLint working directories if needed (adjust based on project)
    // "eslint.workingDirectories": [{ "mode": "auto" }],

    // General editor settings
    "editor.formatOnSave": true, // Automatically format code on save
    "[typescript]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode" // Use Prettier for TypeScript
    },
    "[typescriptreact]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode" // Use Prettier for TSX
    }
  },

  // --- VS Code Extensions: To install inside the container ---
  "extensions": [
    "dbaeumer.vscode-eslint",       // ESLint integration
    "esbenp.prettier-vscode",       // Prettier code formatter
    "ms-azuretools.vscode-docker",  // Docker management extension
    "github.vscode-pull-request-github", // GitHub Pull Requests and Issues integration
    "cweijan.vscode-postgresql-client2", // PostgreSQL client (optional, for DB inspection)
    "arcanis.vscode-zipfs"          // Recommended for Yarn PnP support (improves 'Go to Definition')
  ],

  // --- Lifecycle Commands ---
  // Command executed once after the container is created. Installs dependencies using Yarn 4 via Corepack.
  "postCreateCommand": "corepack enable && yarn install",

  // Optional: Command executed every time VS Code attaches to the container.
  // Useful for automatically starting the development server.
  // "postAttachCommand": "yarn dev",

  // Optional but recommended for Yarn PnP: Command to configure VS Code SDKs.
  // Run this manually in the integrated terminal once VS Code is attached:
  // > yarn dlx @yarnpkg/sdks vscode

  // Specify the user VS Code and terminal processes should run as inside the container
  "remoteUser": "node"
}

c) .devcontainer/nginx/default.conf

# .devcontainer/nginx/default.conf
# Nginx configuration: HTTP redirect and HTTPS proxy to Backstage frontend

# Server block to listen on HTTP port 80 and redirect to HTTPS
server {
    listen 80;
    server_name localhost; # Or your specific development domain if any

    # Log redirects (optional)
    # access_log /var/log/nginx/access.log main;
    # error_log /var/log/nginx/error.log warn;

    location / {
        # Permanent redirect (301) to the HTTPS version on the mapped host port (8443)
        return 301 https://$host:8443$request_uri;
    }
}

# Main server block listening on port 443 for HTTPS traffic
server {
    listen 443 ssl http2; # Enable SSL and HTTP/2
    server_name localhost; # Should ideally match the CN in your certificate

    # SSL Certificate files (paths match volume mounts in docker-compose.yml)
    ssl_certificate /etc/nginx/certs/nginx.crt;
    ssl_certificate_key /etc/nginx/certs/nginx.key;

    # Modern SSL/TLS settings (recommended for security)
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers off;
    # Example cipher suite (adjust based on security requirements)
    ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    # Optional: Add security headers
    # add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
    # add_header X-Frame-Options DENY always;
    # add_header X-Content-Type-Options nosniff always;
    # add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    # Log configuration (optional)
    # access_log /var/log/nginx/access.log main;
    # error_log /var/log/nginx/error.log warn;

    # Root location: Proxy all requests to the Backstage application service
    location / {
        # The target service name 'app' and port '7007' from docker-compose.yml
        proxy_pass http://app:7007;

        # Set headers to pass information to the backend (Backstage)
        proxy_set_header Host $host;                   # Pass the original host requested by the client
        proxy_set_header X-Real-IP $remote_addr;       # Pass the real client IP address
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # Append client IP list
        proxy_set_header X-Forwarded-Proto $scheme;    # Pass the original request scheme (http or https)
        proxy_set_header X-Forwarded-Host $host;       # Pass original host (sometimes needed)
        proxy_set_header X-Forwarded-Port $server_port;# Pass original port (sometimes needed)


        # WebSocket support (important if Backstage uses WebSockets)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;        # Allow upgrading the connection to WebSocket
        proxy_set_header Connection "upgrade";         # Set connection header for WebSocket

        # Optional: Adjust timeouts for long-running requests if necessary
        # proxy_connect_timeout 75s;
        # proxy_read_timeout 300s;
        # proxy_send_timeout 300s;
    }

    # Add other specific Nginx location blocks or directives if needed for your setup
    # Example: Serving static files directly from Nginx
    # location /static/ {
    #     alias /path/to/static/files/in/nginx/container;
    #     expires 1d;
    # }
}

3. 如何使用

系统要求:

  • 安装 Docker Desktop (或适用于 Linux 的 Docker Engine + Docker Compose)。
  • 安装 Visual Studio Code。
  • 安装 VS Code 的 "Dev Containers" 扩展 (ID: ms-vscode-remote.remote-containers)。

放置文件:

  • docker-compose.ymldevcontainer.json 放入项目根目录下的 .devcontainer 文件夹。
  • nginx/default.conf 放入 .devcontainer/nginx/default.conf
  • 确保按照步骤 1 生成的 nginx.keynginx.crt 位于 .devcontainer/nginx/certs/

配置 Yarn 版本 (关键):

  1. 打开你项目根目录下的 package.json 文件。
  2. 确保存在 "packageManager" 字段,并指向你希望使用的 Yarn 4 版本。例如:
// package.json snippet
{
  "name": "my-backstage-project",
  // ... other fields
  "packageManager": "yarn@4.1.1" // Or another Yarn 4+ version
}
  1. 如果项目中没有 package.json 或者没有此字段,corepack enable 可能无法正确启用 Yarn 4。你可能需要在容器启动后手动运行 yarn set version stable 或类似命令。

启动 Dev Container:

  1. 在 VS Code 中,使用 File > Open Folder... 打开你的项目根目录。
  2. VS Code 右下角应出现提示:"Folder contains a Dev Container configuration file. Reopen folder to develop in a container." (或类似中文提示)。
  3. 点击 "Reopen in Container" 按钮。

构建与启动:

  • VS Code 的 Dev Containers 扩展将根据 .devcontainer/devcontainer.json.devcontainer/docker-compose.yml 配置来构建(如果需要)并启动所有服务 (app, db, nginx)。
  • postCreateCommand (corepack enable && yarn install) 会自动执行,安装项目依赖。首次启动可能需要一些时间下载镜像和安装依赖。

访问服务:

  • Backstage UI (通过 Nginx HTTPS): 打开浏览器访问 https://localhost:8443。你需要接受浏览器关于自签名证书的安全警告。
  • HTTP 到 HTTPS 重定向: 访问 http://localhost:8080 应该会自动跳转到 https://localhost:8443
  • 直接访问 Backstage (不通过 Nginx): http://localhost:7007
  • 数据库: 数据库运行在 db 服务中,app 服务可以通过 db:5432 访问。如果需要从宿主机直接访问,请取消 docker-compose.ymldb 服务的端口映射注释。

Yarn PnP 与 VS Code 集成 (若使用 PnP):

  • 如果你的 Backstage 项目配置为使用 Yarn Plug'n'Play (PnP),为了让 VS Code 的 IntelliSense (特别是 TypeScript 的 "Go to Definition" 等功能) 正常工作,建议在容器启动并附加 VS Code 后,在 VS Code 的集成终端中运行一次以下命令:
yarn dlx @yarnpkg/sdks vscode
  • 这将生成或更新 VS Code 所需的 PnP 配置。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment