# Install HashiCorp Vault with Docker: Secrets, Policies and Terraform

> Run Vault in dev mode, store secrets in the KV engine, restrict access with policies and tokens, and read them from the CLI, curl and Terraform.

- Source: https://www.itwonderlab.com/install-vault-docker/
- Published: 2026-09-13
- Updated: 2026-09-13
- Author: Javier Ruiz Jiménez (https://www.javierruizjimenez.com/)
- Site: IT Wonder Lab (https://www.itwonderlab.com/)

---

## What is Vault

[Vault](https://www.itwonderlab.com/vault/) stores secrets and controls who can read them. Instead of putting a database password in a file, an application authenticates to Vault and reads it at runtime, and every access is audited. In this tutorial you run Vault in a container, write secrets, create a restrictive policy and read a secret from Terraform.

> [!WARNING]
> The **dev mode** used here keeps everything in memory, has no TLS and is unsealed with a known root token. Use it only to learn. For production, configure storage, TLS, auto-unseal and an authentication method.

## Run Vault

```bash
docker run -d --name vault --cap-add=IPC_LOCK -p 8200:8200 \
  -e VAULT_DEV_ROOT_TOKEN_ID=dev-token \
  hashicorp/vault
```

Install the `vault` CLI (see [Packer](https://www.itwonderlab.com/packer-build-aws-ami/) for the HashiCorp repository) or run it inside the container with `docker exec`. Point it to the server:

```bash
export VAULT_ADDR=http://127.0.0.1:8200
export VAULT_TOKEN=dev-token
vault status
```

The web interface is at `http://localhost:8200` (sign in with the token).

## Store and read secrets

Dev mode mounts a KV version 2 engine at `secret/`.

```bash
vault kv put -mount=secret myapp username=app password=s3cr3t
vault kv get -mount=secret myapp
vault kv get -mount=secret -field=password myapp
vault kv put -mount=secret myapp username=app password=n3w   # new version
vault kv get -mount=secret -version=1 myapp
```

KV v2 keeps previous versions, so a change can be rolled back.

## Policies and tokens

A policy lists paths and what can be done with them. The default root token can do everything, so create a token for an application that can only read one path:

```hcl title="myapp-read.hcl"
path "secret/data/myapp" {
  capabilities = ["read"]
}
```

```bash
vault policy write myapp-read myapp-read.hcl
vault token create -policy=myapp-read -ttl=1h
```

Use the new token and check the limits:

```bash
VAULT_TOKEN=<new token> vault kv get -mount=secret myapp                  # works
VAULT_TOKEN=<new token> vault kv put -mount=secret myapp password=x       # permission denied
```

Note that KV v2 paths contain `data/` in policies and in the HTTP API.

## The HTTP API

```bash
curl -s -H "X-Vault-Token: $VAULT_TOKEN" $VAULT_ADDR/v1/secret/data/myapp | jq .data.data
```

Any language can use this API, which is why Vault works with every platform. See [jq](https://www.itwonderlab.com/jq/) for the filter.

## Authentication methods for applications

Humans use a token or OIDC. Machines should not hold a long-lived token: use **AppRole**, the **Kubernetes** method or the **AWS** method, where the workload proves its identity with its service account or IAM role and gets a short-lived token.

```bash
vault auth enable approle
vault write auth/approle/role/myapp token_policies=myapp-read token_ttl=15m
vault read auth/approle/role/myapp/role-id
vault write -f auth/approle/role/myapp/secret-id
```

## Read a secret in Terraform

```hcl title="main.tf"
provider "vault" {
  address = "http://127.0.0.1:8200"
  # token comes from the VAULT_TOKEN variable
}

data "vault_kv_secret_v2" "app" {
  mount = "secret"
  name  = "myapp"
}

output "username" {
  value = data.vault_kv_secret_v2.app.data["username"]
}
```

Secrets read this way end up in the Terraform state, so protect the state ([state encryption](https://www.itwonderlab.com/terraform-state-file-encryption/) and [secrets management](https://www.itwonderlab.com/terraform-secrets-management/)). For values that must not be stored, use ephemeral resources in recent Terraform versions or inject secrets at runtime.

## Alternatives

On AWS, [Secrets Manager](https://www.itwonderlab.com/aws-secrets-manager/) and [KMS](https://www.itwonderlab.com/aws-kms/) cover most needs without running a server. Vault is the choice for multi-cloud, dynamic credentials and one place to audit access.

## Clean up

```bash
docker rm -f vault
```
