SDK
Docker & Docker Compose

Dev Containers

CodeSandbox natively supports the Dev Containers specification (opens in a new tab), allowing you to customize your sandbox, install system-level dependencies, and run additional services.

Configuration

To configure your sandbox environment, create a .devcontainer/devcontainer.json file inside the root of the sandbox:

{
  "name": "Node.js",
  "image": "mcr.microsoft.com/devcontainers/javascript-node:18",
  "features": {
    "ghcr.io/devcontainers/features/python:1": {}
  }
}

In this example, we're installing Node v18 as base, with Python on top using Dev Container Features.

Alternatively, you can use a Dockerfile to build the Docker image when the sandbox boots:

{
  "name": "Node.js",
  "build": {
    "dockerfile": "./Dockerfile"
  }
}

Using Dev Containers in the SDK

When creating a sandbox, all shells will automatically run inside the Docker container specified in the Dev Container configuration.

const sandbox = await sdk.sandbox.create({
  template: "node" // Template with Dev Container configuration
});
 
await sandbox.shells.run("node --version");

Since we use memory snapshots, the Docker container will already be running when you run your shell.

Docker Compose

You can run additional services using Docker Compose by adding a docker-compose.yml configuration to your Dev Container:

{
  "name": "Full Stack App",
  "dockerComposeFile": "docker-compose.yml",
  "service": "app",
  "workspaceFolder": "/workspace"
}

With a corresponding docker-compose.yml:

services:
  app:
    image: mcr.microsoft.com/devcontainers/javascript-node:18
    command: sleep infinity
 
  db:
    image: postgres:14
    ports:
      - 5432:5432
    environment:
      POSTGRES_PASSWORD: password

Using Docker Compose in the SDK

The SDK will automatically start all services defined in your Docker Compose configuration:

const sandbox = await sdk.sandbox.create({
  template: "fullstack" // Template with Dev Container configuration
});
 
// Wait for all services to be ready
await sandbox.setup.waitForFinish();
 
// You can now connect to the services
const portInfo = await sandbox.ports.waitForPort(5432);
console.log(`Database available at: ${portInfo.hostname}:${portInfo.port}`);

Examples

Full-Stack Development Environment

Here's an example of setting up a full-stack development environment with Node.js and PostgreSQL:

const sandbox = await sdk.sandbox.create({
  template: "fullstack"
});
 
// Wait for environment setup
const progress = await sandbox.setup.waitForFinish();
if (progress.state !== "FINISHED") {
  throw new Error("Environment setup failed");
}
 
// Start the development server
const devTask = await sandbox.tasks.runTask("dev");
 
// Wait for both the app and database to be ready
const [appPort, dbPort] = await Promise.all([
  sandbox.ports.waitForPort(3000),
  sandbox.ports.waitForPort(5432)
]);
 
console.log(`
App running at: ${appPort.getPreviewUrl()}
Database available at: ${dbPort.hostname}:${dbPort.port}
`);

Custom Environment with System Dependencies

Example of a sandbox that needs specific system packages:

const sandbox = await sdk.sandbox.create({
  template: "custom-env"
});
 
// The Dev Container will install required packages during setup
await sandbox.setup.waitForFinish();
 
// Run a command that uses the installed packages
const result = await sandbox.shells.run("ffmpeg -version");
console.log(result.output);

For more information about Dev Container configuration options and features, visit the Dev Container specification (opens in a new tab). Also, take a look at our snapshot builder to learn how to create efficient snapshots with preloaded Docker images.