Using ENV with Docker

When building a docker image to run/deploy your application you have two options for loading secrets.

Prerequisites

Before getting started with ENV service, ensure you have:

  • Signed up for a Hyphen account and have access to an organization
  • Have the hx command line installed and authenticated

Sample Docker configuration

Here’s a basic configuration for your Docker environment.

FROM node:20-alpine3.16 as base

#########################################

FROM base as builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . ./
RUN npm run build

#########################################

FROM base as server
WORKDIR /app
COPY  --chown=node:node --from=builder /node_modules ./node_modules
COPY  --chown=node:node --from=builder /dist ./dist
ENV PORT 3000
EXPOSE 3000
USER node
CMD ["npm", "run", "start-prod"]
node_modules/
.hxkey

Option 1: Using hyphen-entrypoint.sh

Pros

  • Secrets rotation only requires a container restart
  • Treats secrets like secrets and makes them available only at runtime.
  • One-time setup works consistently across environments and CI/CD and doesn't require changes when new secrets are added

Cons

  • Differs from how the application is developed

When you run hx init, a hyphen-entrypoint.sh script is automatically created in your project directory. This script is designed specifically for Docker deployments and handles:

  1. Downloading the Hyphen CLI if not already present
  2. Authenticating with your Hyphen API key
  3. Pulling environment variables for the specified environment
  4. Running your application with those variables loaded

Note: If the hyphen-entrypoint.sh is missing (e.g. because you ran init with an older version of hx) or needs to be updated, you can re-create it with hx entrypoint (and use --force if needed to overwrite it).

Required Environment Variables

The entrypoint script requires five environment variables to be set in your container:

  • HYPHEN_API_KEY: Your Hyphen API key for authentication
  • HYPHEN_APP_ENVIRONMENT: The environment to pull variables from (e.g., "development", "production", "default")
  • HYPHEN_APP_ID: Your application ID (e.g., "app_68f65adbb2aca958a8ff6ea9")
  • HYPHEN_PROJECT_ID: Your project ID (e.g., "proj_68ee9033968a1e3b98be5501")
  • HYPHEN_ORGANIZATION_ID: Your organization ID (e.g., "org_681bd71a0cd803794aebd33a")

Sample Dockerfile with Entrypoint

FROM node:20-alpine3.16 AS base

#########################################

FROM base AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . ./
RUN npm run build

#########################################

FROM base AS server
WORKDIR /app
COPY --chown=node:node --from=builder /app/package.json ./package.json
COPY --chown=node:node --from=builder /app/dist ./dist
COPY --chown=node:node --from=builder /app/hyphen-entrypoint.sh ./hyphen-entrypoint.sh
RUN chown -R node:node /app
RUN chmod +x ./hyphen-entrypoint.sh
ENV PORT=3000
EXPOSE 3000
USER node
ENTRYPOINT ["./hyphen-entrypoint.sh"]
CMD ["npm", "run", "start-prod"]

Build and Run

docker build . -t my-org/my-app
docker run -t my-org/my-app \
  -e HYPHEN_API_KEY=$HYPHEN_API_KEY \
  -e HYPHEN_APP_ENVIRONMENT=production \
  -e HYPHEN_APP_ID=app_YOUR_APP_ID \
  -e HYPHEN_PROJECT_ID=proj_YOUR_PROJECT_ID \
  -e HYPHEN_ORGANIZATION_ID=org_YOUR_ORG_ID

You can find these IDs in your .hx file after running hx init, or in the Hyphen dashboard.

The entrypoint script will automatically handle downloading the CLI, authenticating, pulling secrets, and starting your application with the correct environment variables loaded.

Option 2: Including .env files

Pros

  • Quickest way to get started
  • Mirrors how the application is developed

Cons

  • Requires creating a new docker image to rotate secrets

If you choose to include your .env files in the container, you will need to:

  1. Pull the secrets
  2. Copy them into your container
  3. Use an open-source library to read them into your application.

More information on .env files and the many open-source libraries can be found at https://www.dotenv.org/


> hx pull default && hx pull production

It's best practice to only pull secrets for the specific environment you're running in, which is why we didn't just run hx pull.

docker build . -t my-org/my-app

Given that the DOCKERFILE copies the contents of the directory into the image, this will copy over the .env files, making them available to your application.

Option 3: Exporting Secrets

Pros

  • Secrets rotation only requires a container restart
  • Treats secrets like secrets and makes them available only at runtime.

Cons

  • Differs from how the application is developed
  • Requires more setup

Running the hx env run command will export all secrets as environment variables, which you can reference as needed. In this example, we pass them to the docker run command, though you could also mount them during the build. This is often how secrets are passed to cloud providers (e.g., Google Cloud Run).

docker build . -t my-org/my-app
# Single environment variable
hx env run production -- sh -c 'docker run -t my-org/my-app -e MY_SECRET=$MY_SECRET'

# Multiple environment variables
hx env run production -- sh -c 'docker run -t my-org/my-app \
    -e MY_SECRET=$MY_SECRET \
    -e API_KEY=$API_KEY \
    -e DB_PASSWORD=$DB_PASSWORD'