Docker Compose
You can use Phase Run to inject secrets to your application process during runtime. There's no need for you to change any code or add a dependency.
Prerequisites
- Have signed up for the Phase Console and created an application.
PHASE_SERVICE_TOKEN(Ideally for each of your services).
If you are using a Self-Hosted instance of the Phase Console, you may supply
PHASE_HOST environment variable with your URL (https://<HOST>).
Using Phase Run
This method uses the Phase CLI to inject secrets into your docker compose services without requiring any change in your docker file.
- Reference the required environment variables directly in your
docker-compose.yml:
Only the secrets explicitly listed inside the environment: map will be
supplied to your services. Make sure to update the list every time you add a
new secret in Phase.
services:
web:
build: .
image: example-service-1
# 👇 Explicitly mention each secret that you want to supply to each service
environment:
- SECRET_VAR
- REDIS_HOST
- REDIS_PASSWORD
depends_on:
- redis
api:
build: .
image: example-service-2
environment:
# 👇 Explicitly mention each secret that you want to supply to each service
- ANOTHER_SECRET
- PG_HOST
- PG_USER
- PG_PASSWORD
- PG_DB_NAME
depends_on:
- pgql
pgql:
image: postgres:latest
environment:
# 👇 Explicitly mention each secret that you want to supply to each service
- POSTGRES_USER
- POSTGRES_PASSWORD
- POSTGRES_DB
ports:
- '5432:5432'
volumes:
- pgdata:/var/lib/postgresql/data
redis:
image: redis:latest
environment:
# 👇 Explicitly mention each secret that you want to supply to each service
- REDIS_PASSWORD
- '6379:6379'
volumes:
pgdata:
- Inject secrets into
docker compose:
phase run --app "my application name" docker compose up -d
Using Docker Compose secrets with Phase Run
This method combines Phase Run's secret injection with Docker Compose's native secrets feature, without writing any secrets on disk for enhanced security. Environment variables are often available to all processes; it can be difficult to track access. They can also be printed in logs when debugging errors without your knowledge. Using secrets mitigates these risks. Instead of passing sensitive data as environment variables, secrets are mounted as files inside the container. More information over at Docker Compose docs.
This approach requires your application to be configured to read secrets from files rather than environment variables.
- Reference the required secrets directly in your
docker-compose.ymlusing the top-levelsecretselement along with the services which require access to each secret using thesecretsattribute:
services:
api:
build: .
image: example-service
environment:
# Non-sensitive configuration
- API_PORT=3000
secrets:
# 👇 Secrets will be mounted under /run/secrets/*
- api_key
- db_password
command: ["./wait-for-secrets.sh", "node", "server.js"]
db:
image: postgres:latest
environment:
# 👇 So postgresql knows where to find the password file
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_password
volumes:
- pgdata:/var/lib/postgresql/data
secrets:
api_key:
# 👇 This key must be the same as your secret in Phase
environment: 'API_KEY'
db_password:
# 👇 This key must be the same as your secret in Phase
environment: 'POSTGRES_PASSWORD'
volumes:
pgdata:
- Inject secrets into
docker compose:
phase run --app "my application name" docker compose up -d
Using Docker CMD
This method uses the Phase CLI running inside each of your Docker containers to inject secrets to your application at runtime. You will need to install the Phase CLI inside each of your Containers and adjust your CMD to add the phase run command as prefix.
- Installing the Phase CLI in Your Docker Container
To maintain deterministic Docker builds and prevent accidentally breaking things, it's recommended to specify the --version flag. You can find the latest versions of the CLI at the GitHub releases. If no version flag is provided then the latest version of the CLI will be installed.
ENV VERSION=<X.XX.XX>
RUN apk add --no-cache curl && curl -fsSL https://pkg.phase.dev/install.sh | sh -s -- --version $VERSION
- Defining Your Container's Start Command
Use CMD to specify the default command to run when starting your container, offering flexibility to override it easily. For initializing the Phase CLI with or without a .phase.json, including the --app and --env flags as context.
For a Single Command:
FROM your-base-image
# ... (other Docker commands, e.g., installing dependencies, copying source code, etc.)
# Use CMD to define the default command. Include --app, --env, and optionally --version flags to specify context.
CMD ["sh", "-c", "phase run --app \"my application name\" --env \"production\" yarn start"]
For Multiple Commands:
FROM your-base-image
# ... (other Docker commands, e.g., installing dependencies, etc.)
# Use CMD to define a series of commands with correct format and escaping, including Phase CLI version specification if needed.
CMD ["sh", "-c", "phase run \"python manage.py migrate && python manage.py runserver payments-api:8000\""]
- Set
PHASE_SERVICE_TOKENas an environment variable.
export PHASE_SERVICE_TOKEN_FOR_WEB=<YOUR_PHASE_SERVICE_TOKEN_FOR_WEB>
export PHASE_SERVICE_TOKEN_FOR_API=<YOUR_PHASE_SERVICE_TOKEN_FOR_API>
- Create or edit your
docker-compose.yml:
services:
web:
build: .
image: example-service-1
environment:
- PHASE_SERVICE_TOKEN=${PHASE_SERVICE_TOKEN_FOR_WEB}
api:
build: .
image: example-service-2
environment:
- PHASE_SERVICE_TOKEN=${PHASE_SERVICE_TOKEN_FOR_API}
Using eval
This method lets you export all secrets stored in Phase as environment variable on the host system which can be used by docker compose.
- Export secrets as environment variables in your shell.
eval $(phase secrets export --app "my application name" --env development)
- Reference these environment variables directly in your
docker-compose.yml:
services:
web:
build: .
image: example-service-1
# 👇 Explicitly mention each secret that you want to supply to each service
environment:
- SECRET_VAR
- REDIS_HOST
- REDIS_PASSWORD
depends_on:
- redis
api:
build: .
image: example-service-2
environment:
# 👇 Explicitly mention each secret that you want to supply to each service
- ANOTHER_SECRET
- PG_HOST
- PG_USER
- PG_PASSWORD
- PG_DB_NAME
depends_on:
- pgql
pgql:
image: postgres:latest
environment:
# 👇 Explicitly mention each secret that you want to supply to each service
- POSTGRES_USER
- POSTGRES_PASSWORD
- POSTGRES_DB
ports:
- '5432:5432'
volumes:
- pgdata:/var/lib/postgresql/data
redis:
image: redis:latest
environment:
# 👇 Explicitly mention each secret that you want to supply to each service
- REDIS_PASSWORD
- '6379:6379'
volumes:
pgdata:
Using Phase Export
This method lets you export all secrets stored in Phase to a file on disk and supply them to docker compose via env_file:.
- Export secrets as environment variables in your shell.
phase secrets export --app "my application name" --env development > secrets.env
- Reference these environment variables directly in your
docker-compose.yml:
services:
web:
build: .
image: example-service-1
# 👇 Path to the file where you exported secrets to
env_file:
- secrets.env
depends_on:
- redis
api:
build: .
image: example-service-2
# 👇 Path to the file where you exported secrets to
env_file:
- secrets.env
depends_on:
- pgql
pgql:
image: postgres:latest
# 👇 Path to the file where you exported secrets to
env_file:
- secrets.env
ports:
- '5432:5432'
volumes:
- pgdata:/var/lib/postgresql/data
redis:
image: redis:latest
# 👇 Path to the file where you exported secrets to
env_file:
- secrets.env
volumes:
pgdata: