> ## Documentation Index
> Fetch the complete documentation index at: https://cdktn.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Install CDK Terrain and run a quick start demo

> Install the CDK Terrain CLI, initialize a project in your preferred language, and deploy the Docker-based quick start container.

export const PlatformDiagram = () => {
  return <svg viewBox="0 0 800 520" width="100%" role="img" aria-label="CDK Terrain platform diagram showing supported languages, the CDK Terrain layer, OpenTofu and Terraform engine, and cloud providers" style={{
    maxWidth: 800,
    margin: "0 auto",
    display: "block"
  }}>
      <title>CDK Terrain Platform Overview</title>

      <defs>
        <marker id="arrowGray" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
          <path d="M 0 0 L 10 5 L 0 10 z" fill="#9ca3af" />
        </marker>
      </defs>

      {}
      <rect x="100" y="20" width="600" height="50" rx="8" fill="#f3f4f6" stroke="#d1d5db" strokeWidth="1.5" />
      <text x="175" y="51" textAnchor="middle" fontSize="15" fontFamily="system-ui, sans-serif" fontWeight="500" fill="#374151">TypeScript</text>
      <line x1="240" y1="30" x2="240" y2="60" stroke="#d1d5db" strokeWidth="1" />
      <text x="300" y="51" textAnchor="middle" fontSize="15" fontFamily="system-ui, sans-serif" fontWeight="500" fill="#374151">Python</text>
      <line x1="360" y1="30" x2="360" y2="60" stroke="#d1d5db" strokeWidth="1" />
      <text x="420" y="51" textAnchor="middle" fontSize="15" fontFamily="system-ui, sans-serif" fontWeight="500" fill="#374151">Java</text>
      <line x1="480" y1="30" x2="480" y2="60" stroke="#d1d5db" strokeWidth="1" />
      <text x="540" y="51" textAnchor="middle" fontSize="15" fontFamily="system-ui, sans-serif" fontWeight="500" fill="#374151">C#</text>
      <line x1="600" y1="30" x2="600" y2="60" stroke="#d1d5db" strokeWidth="1" />
      <text x="660" y="51" textAnchor="middle" fontSize="15" fontFamily="system-ui, sans-serif" fontWeight="500" fill="#374151">Go</text>

      {}
      <line x1="400" y1="70" x2="400" y2="110" stroke="#9ca3af" strokeWidth="2" markerEnd="url(#arrowGray)" />

      {}
      <rect x="200" y="110" width="400" height="60" rx="10" fill="#16A34A" />
      <text x="400" y="147" textAnchor="middle" fontSize="20" fontFamily="system-ui, sans-serif" fontWeight="700" fill="white">CDK Terrain (CDKTN)</text>

      {}
      <line x1="400" y1="170" x2="400" y2="220" stroke="#9ca3af" strokeWidth="2" markerEnd="url(#arrowGray)" />

      {}
      <rect x="150" y="220" width="500" height="80" rx="12" fill="#15803D" />

      {}
      <g transform="translate(290, 235) scale(1.3)">
        <path fill="#E6C220" d="M18.66,2.33c.2-.11,.44-.11,.64,0l14.2,7.81c.46,.25,.46,.91,0,1.16l-14.2,7.81c-.2,.11-.44-.11-.64,0L4.46,11.3c-.46-.25-.46-.91,0-1.16L18.66,2.33Z" />
        <path fill="#FFFFFF" d="M34.77,13.13c.44-.24,.98,.08,.98,.58v15.61c0,.24-.13,.47-.34,.58l-14.34,7.88c-.44,.24-.98-.08-.98-.58v-15.61c0-.24,.13-.47,.34-.58l14.34-7.88Z" />
        <path fill="#FEDA15" d="M17.53,21.01L3.2,13.13c-.44-.24-.98,.08-.98,.58v15.61c0,.24,.13,.47,.34,.58l14.34,7.88c.44,.24,.98-.08,.98-.58v-15.61c0-.24-.13-.47-.34-.58Zm-9.3,4.97l-3.36-1.77s0-.01,0-.02c.08-1.05,.89-1.5,1.82-1.01,.93,.49,1.62,1.73,1.54,2.78,0,0,0,.01,0,.02Zm5.29,3.05l-3.36-1.77s0-.01,0-.02c.08-1.05,.89-1.5,1.82-1.01,.93,.49,1.62,1.73,1.54,2.78,0,0,0,.01,0,.02Z" />
      </g>

      <text x="350" y="270" textAnchor="start" fontSize="22" fontFamily="system-ui, sans-serif" fontWeight="700" fill="white">OpenTofu</text>
      <text x="476" y="270" textAnchor="start" fontSize="15" fontFamily="system-ui, sans-serif" fontWeight="400" fill="rgba(255,255,255,0.7)">/ Terraform</text>

      {}
      <line x1="400" y1="300" x2="400" y2="350" stroke="#9ca3af" strokeWidth="2" />

      {}
      <line x1="400" y1="350" x2="100" y2="350" stroke="#9ca3af" strokeWidth="2" />
      <line x1="400" y1="350" x2="700" y2="350" stroke="#9ca3af" strokeWidth="2" />
      <line x1="100" y1="350" x2="100" y2="390" stroke="#9ca3af" strokeWidth="2" markerEnd="url(#arrowGray)" />
      <line x1="220" y1="350" x2="220" y2="390" stroke="#9ca3af" strokeWidth="2" markerEnd="url(#arrowGray)" />
      <line x1="340" y1="350" x2="340" y2="390" stroke="#9ca3af" strokeWidth="2" markerEnd="url(#arrowGray)" />
      <line x1="460" y1="350" x2="460" y2="390" stroke="#9ca3af" strokeWidth="2" markerEnd="url(#arrowGray)" />
      <line x1="580" y1="350" x2="580" y2="390" stroke="#9ca3af" strokeWidth="2" markerEnd="url(#arrowGray)" />
      <line x1="700" y1="350" x2="700" y2="390" stroke="#9ca3af" strokeWidth="2" markerEnd="url(#arrowGray)" />

      {}
      <rect x="40" y="395" width="120" height="50" rx="8" fill="#f9fafb" stroke="#d1d5db" strokeWidth="1.5" />
      <text x="100" y="425" textAnchor="middle" fontSize="14" fontFamily="system-ui, sans-serif" fontWeight="600" fill="#374151">AWS</text>

      <rect x="160" y="395" width="120" height="50" rx="8" fill="#f9fafb" stroke="#d1d5db" strokeWidth="1.5" />
      <text x="220" y="425" textAnchor="middle" fontSize="14" fontFamily="system-ui, sans-serif" fontWeight="600" fill="#374151">Azure</text>

      <rect x="280" y="395" width="120" height="50" rx="8" fill="#f9fafb" stroke="#d1d5db" strokeWidth="1.5" />
      <text x="340" y="425" textAnchor="middle" fontSize="14" fontFamily="system-ui, sans-serif" fontWeight="600" fill="#374151">GCP</text>

      <rect x="400" y="395" width="120" height="50" rx="8" fill="#f9fafb" stroke="#d1d5db" strokeWidth="1.5" />
      <text x="460" y="425" textAnchor="middle" fontSize="14" fontFamily="system-ui, sans-serif" fontWeight="600" fill="#374151">Kubernetes</text>

      <rect x="520" y="395" width="120" height="50" rx="8" fill="#f9fafb" stroke="#d1d5db" strokeWidth="1.5" />
      <text x="580" y="425" textAnchor="middle" fontSize="14" fontFamily="system-ui, sans-serif" fontWeight="600" fill="#374151">Docker</text>

      <rect x="640" y="395" width="120" height="50" rx="8" fill="#f9fafb" stroke="#d1d5db" strokeWidth="1.5" />
      <text x="700" y="419" textAnchor="middle" fontSize="14" fontFamily="system-ui, sans-serif" fontWeight="600" fill="#374151">3000+</text>
      <text x="700" y="437" textAnchor="middle" fontSize="12" fontFamily="system-ui, sans-serif" fontWeight="400" fill="#6b7280">providers</text>
    </svg>;
};

<Note>
  This guide was recovered from the [Wayback Machine snapshot of “Install CDK for Terraform and run a quick start demo”](https://web.archive.org/web/20251115095039https://developer.hashicorp.com/terraform/tutorials/cdktf/cdktf-install).
</Note>

CDK Terrain (CDKTN) lets you define infrastructure in familiar programming languages while still creating plans with Terraform (or OpenTofu). You can use CDKTN with hundreds of providers and existing modules, adopt Terraform Cloud/HCP Terraform workflows, and ship infrastructure with the development practices you already use for application code.

<PlatformDiagram />

Follow this tutorial to install the CDKTN CLI and run the quick start project that provisions an NGINX container with Docker.

## Prerequisites

* Terraform CLI 1.2+ (or [OpenTofu](https://opentofu.org/))
* Node.js 16+ and npm 16+
* Docker Desktop or another Docker runtime
* Your preferred CDKTN language toolchain (TypeScript v4.4 + Node.js 16.13, Python 3.10 + Pipenv, Go 1.20+, .NET 6+, or Java 17 with Maven)

## Install CDKTN

You can install the `cdktn` CLI globally with npm on any platform or with Homebrew on macOS. Pick the option that matches how you manage global tools.

<Tabs>
  <Tab title="npm (stable)">
    ```shell Shell theme={null}
    npm install --global cdktn-cli@latest
    ```
  </Tab>

  <Tab title="npm (development)">
    ```shell Shell theme={null}
    npm install --global cdktn-cli@next
    ```
  </Tab>

  <Tab title="Homebrew (macOS)">
    ```shell Shell theme={null}
    brew install cdktn
    ```
  </Tab>
</Tabs>

<Tip>CDKTN works with both Terraform and OpenTofu. To run OpenTofu, set `TERRAFORM_BINARY_NAME=tofu` before using the CLI. Refer to [Environment Variables](/create-and-deploy/environment-variables) for details.</Tip>

## Verify the installation

Confirm that the CLI is on your `PATH` and review the available subcommands.

```shell-session Shell theme={null}
cdktn help
cdktn

Commands:
  cdktn init   Create a new cdktn project from a template.
  cdktn deploy Deploy the given stacks (aliases: apply)
  cdktn destroy Destroy the given stacks
  cdktn synth  Synthesize Terraform configuration for your app

Options:
  --version  Show version number
  -h, --help Show help
```

Use `cdktn init --help` whenever you need more detail on initialization flags.

```shell-session Shell theme={null}
cdktn init --help

Create a new cdktn project from a template.

Options include:
  --template <name|url>   Built-in templates: csharp, go, java, python, python-pip, typescript
  --project-name <text>   Project directory name
  --providers <list>      Comma-separated providers to preconfigure
  --local                 Store Terraform state locally (default false)
  --cdktn-version <tag>   CLI version to scaffold with
```

## Quick start tutorial

The following steps install dependencies, generate the sample application, edit the stack, and deploy the Docker container. The commands are identical across languages unless otherwise noted.

### Create and initialize the project

Create a workspace for the tutorial and move into it.

```shell Shell theme={null}
mkdir learn-cdktn-docker
cd learn-cdktn-docker
```

Initialize the project in your preferred language and add the Docker provider. The `--local` flag keeps Terraform state in the project directory, which is convenient for the quick start.

<CodeGroup>
  ```shell-session TypeScript theme={null}
  cdktn init --template=typescript --providers=kreuzwerker/docker --local
  Note: By supplying '--local' option you have chosen local storage mode.
  ? Project Name learn-cdktn-docker
  ? Project Description A simple getting started project for cdktn.
  ? Do you want to start from an existing Terraform project? No
  ? Do you want to send crash reports to the CDKTN team? Yes
  added 301 packages in 6s
  ========================================================================================================
  Your cdktn typescript project is ready!
  ```

  ```shell-session Python theme={null}
  cdktn init --template=python --providers=kreuzwerker/docker --local
  Note: By supplying '--local' option you have chosen local storage mode.
  ? Project Name learn-cdktn-docker
  ? Project Description A simple getting started project for cdktn.
  Creating a virtualenv for this project...
  ✔ Successfully created virtual environment!
  Installing dependencies from Pipfile.lock (c0c5a6)...
  Installing cdktn~=0.15.0.dev59...
  Your cdktn python project is ready!
  ```

  ```shell-session Go theme={null}
  cdktn init --template=go --providers=kreuzwerker/docker --local
  Note: By supplying '--local' option you have chosen local storage mode.
  ? Project Name learn-cdktn-docker
  ? Project Description A simple getting started project for cdktn.
  go: downloading github.com/aws/constructs-go/constructs/v10 v10.1.167
  go: downloading github.com/open-constructs/cdk-terrain-go/cdktn v0.15.0-pre.59
  go: downloading github.com/aws/jsii-runtime-go v1.73.0
  ========================================================================================================
  Your cdktn go project is ready!
  ```

  ```shell-session C# theme={null}
  cdktn init --template=csharp --providers=kreuzwerker/docker --local
  Note: By supplying '--local' option you have chosen local storage mode.
  ? Project Name learn-cdktn-docker
  ? Project Description A simple getting started project for cdktn.
  Determining projects to restore...
  Found pre-built provider.
  Package installed.
  ========================================================================================================
  Your cdktn csharp project is ready!
  ```

  ```shell-session Java theme={null}
  cdktn init --template=java --providers=kreuzwerker/docker --local
  Note: By supplying '--local' option you have chosen local storage mode.
  ? Project Name learn-cdktn-docker
  ? Project Description A simple getting started project for cdktn.
  [INFO] Scanning for projects...
  [INFO] BUILD SUCCESS
  ========================================================================================================
  Your cdktn java project is ready!
  ```
</CodeGroup>

### Edit the code

Replace the generated stack with the following Docker example. Each snippet defines a Docker provider, builds the latest `nginx` image, and provisions a container that exposes port 8000 on your workstation.

<CodeGroup>
  ```ts TypeScript theme={null}
  import { Construct } from "constructs";
  import { App, TerraformStack } from "cdktn";
  import { DockerProvider } from "@cdktn/provider-docker/lib/provider";
  import { Image } from "@cdktn/provider-docker/lib/image";
  import { Container } from "@cdktn/provider-docker/lib/container";

  class MyStack extends TerraformStack {
    constructor(scope: Construct, name: string) {
      super(scope, name);

      new DockerProvider(this, "docker", {});

      const dockerImage = new Image(this, "nginxImage", {
        name: "nginx:latest",
        keepLocally: false,
      });

      new Container(this, "nginxContainer", {
        name: "tutorial",
        image: dockerImage.name,
        ports: [
          {
            internal: 80,
            external: 8000,
          },
        ],
      });
    }
  }

  const app = new App();
  new MyStack(app, "learn-cdktn-docker");
  app.synth();
  ```

  ```python Python theme={null}
  #!/usr/bin/env python

  from constructs import Construct
  from cdktn import App, TerraformStack
  from cdktn_provider_docker.image import Image
  from cdktn_provider_docker.container import Container
  from cdktn_provider_docker.provider import DockerProvider


  class MyStack(TerraformStack):
      def __init__(self, scope: Construct, ns: str) -> None:
          super().__init__(scope, ns)

          DockerProvider(self, "docker")

          docker_image = Image(
              self,
              "nginxImage",
              name="nginx:latest",
              keep_locally=False,
          )

          Container(
              self,
              "nginxContainer",
              name="tutorial",
              image=docker_image.name,
              ports=[
                  {
                      "internal": 80,
                      "external": 8000,
                  }
              ],
          )


  app = App()
  MyStack(app, "learn-cdktn-docker")
  app.synth()
  ```

  ```go Go theme={null}
  package main

  import (
      "github.com/aws/constructs-go/constructs/v10"
      "github.com/aws/jsii-runtime-go"
      "github.com/open-constructs/cdk-terrain-go/cdktn"

      dockercontainer "github.com/cdktn-io/cdktn-provider-docker-go/docker/v3/container"
      dockerimage "github.com/cdktn-io/cdktn-provider-docker-go/docker/v3/image"
      dockerprovider "github.com/cdktn-io/cdktn-provider-docker-go/docker/v3/provider"
  )

  func NewMyStack(scope constructs.Construct, id string) cdktn.TerraformStack {
      stack := cdktn.NewTerraformStack(scope, &id)

      dockerprovider.NewDockerProvider(stack, jsii.String("docker"), &dockerprovider.DockerProviderConfig{})

      dockerImage := dockerimage.NewImage(stack, jsii.String("nginxImage"), &dockerimage.ImageConfig{
          Name:        jsii.String("nginx:latest"),
          KeepLocally: jsii.Bool(false),
      })

      dockercontainer.NewContainer(stack, jsii.String("nginxContainer"), &dockercontainer.ContainerConfig{
          Name:  jsii.String("tutorial"),
          Image: dockerImage.Name(),
          Ports: &[]*dockercontainer.ContainerPorts{
              {
                  Internal: jsii.Number(80),
                  External: jsii.Number(8000),
              },
          },
      })

      return stack
  }

  func main() {
      app := cdktn.NewApp(nil)

      NewMyStack(app, "learn-cdktn-docker")
      app.Synth()
  }
  ```

  ```csharp C# theme={null}
  // MainStack.cs
  using System;
  using Constructs;
  using Io.Cdktn;
  using Io.Cdktn.Providers.Docker.Provider;
  using Io.Cdktn.Providers.Docker.Image;
  using Io.Cdktn.Providers.Docker.Container;

  namespace MyCompany.MyApp;

  class MyApp : TerraformStack
  {
      public MyApp(Construct scope, string id) : base(scope, id)
      {
          new DockerProvider(this, "docker", new DockerProviderConfig { });

          var dockerImage = new Image(this, "nginxImage", new ImageConfig
          {
              Name = "nginx:latest",
              KeepLocally = false,
          });

          new Container(this, "nginxContainer", new ContainerConfig
          {
              Name = "tutorial",
              Image = dockerImage.Name,
              Ports = new[]
              {
                  new ContainerPorts
                  {
                      Internal = 80,
                      External = 8000,
                  },
              },
          });
      }
  }

  // Program.cs
  using System;
  using Constructs;
  using Io.Cdktn;

  namespace MyCompany.MyApp;

  class Program
  {
      public static void Main(string[] args)
      {
          var app = new App();
          new MyApp(app, "learn-cdktn-docker");
          app.Synth();
          Console.WriteLine("App synth complete");
      }
  }
  ```

  ```java Java theme={null}
  // MainStack.java
  package com.mycompany.app;

  import java.util.Arrays;

  import software.constructs.Construct;

  import io.cdktn.cdktn.TerraformStack;
  import io.cdktn.providers.docker.provider.DockerProvider;
  import io.cdktn.providers.docker.image.Image;
  import io.cdktn.providers.docker.container.Container;
  import io.cdktn.providers.docker.container.ContainerPorts;

  public class MainStack extends TerraformStack {
      public MainStack(final Construct scope, final String id) {
          super(scope, id);

          DockerProvider.Builder.create(this, "docker").build();

          Image image = Image.Builder.create(this, "nginxImage")
              .name("nginx:latest")
              .keepLocally(false)
              .build();

          Container.Builder.create(this, "nginxContainer")
              .image(image.getName())
              .name("tutorial")
              .ports(Arrays.asList(
                  ContainerPorts.builder()
                      .internal(80)
                      .external(8000)
                      .build()))
              .build();
      }
  }

  // Main.java
  package com.mycompany.app;

  import io.cdktn.cdktn.App;

  public class Main {
      public static void main(String[] args) {
          final App app = new App();
          new MainStack(app, "learn-cdktn-docker");
          app.synth();
      }
  }
  ```
</CodeGroup>

### Deploy the container

From the project root, run `cdktn deploy` (Terraform or OpenTofu will prompt you to approve the plan). This command synthesizes the application, runs `terraform plan`, and provisions the Docker resources once you enter `approve`.

```shell-session Shell theme={null}
cdktn deploy learn-cdktn-docker
Initializing the backend...
Initializing provider plugins...
Terraform used the selected providers to generate the following execution plan.
Resource actions are indicated with the following symbols:
  + create

# docker_container.nginxContainer will be created
# docker_image.nginxImage will be created

Plan: 2 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
  Enter a value: approve
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
```

Check the container and the mapped port.

```shell Shell theme={null}
docker ps
```

<img src="https://mintcdn.com/cdkterrain/Xq8mBtDxXzz_XPNu/images/tutorials/terraform-docker-nginx.png?fit=max&auto=format&n=Xq8mBtDxXzz_XPNu&q=85&s=906313e2adba942abfb4e9430c57fc1d" alt="NGINX running in Docker via Terraform" width="2048" height="510" data-path="images/tutorials/terraform-docker-nginx.png" />

### Destroy the container

When you finish testing, destroy the stack to remove the Docker container and image.

```shell-session Shell theme={null}
cdktn destroy learn-cdktn-docker
Plan: 0 to add, 0 to change, 2 to destroy.
Do you really want to destroy all resources?
  Enter a value: approve
Destroy complete! Resources: 2 destroyed.
```

## Next steps

* Continue with the [Build AWS infrastructure tutorial](/tutorials/build-aws) to create multi-service stacks.
* Learn how to manage [Lambda functions with assets and stacks](/tutorials/lambda-functions).
* Follow the end-to-end [Deploy applications walkthrough](/tutorials/deploy-applications) to manage multi-stack Kubernetes workloads.

Refer to the navigation sidebar to jump back to Concepts and CLI reference material whenever you need more detail.
