Managing Secrets in Production

In a production environment, it is essential to manage secrets securely. Below is a detailed approach on how to handle secrets within the docker/awesome-compose project, particularly for the nginx-golang backend service.

Dockerfile Configuration

The Dockerfile is a critical part of the infrastructure that defines how the application is built and how secrets can be injected safely without hardcoding them within the application.

# syntax=docker/dockerfile:1.4
FROM --platform=$BUILDPLATFORM python:3.10-alpine AS builder

WORKDIR /code

COPY requirements.txt /code
RUN --mount=type=cache,target=/root/.cache/pip \
    pip3 install -r requirements.txt

COPY . /code

ENTRYPOINT ["python3"]
CMD ["app.py"]

In this Dockerfile, the application code is copied into the image, and Python dependencies are installed. To manage secrets, ensure sensitive information is not included in the Dockerfile or any related files directly.

Using Environment Variables

Environment variables are a common way to manage secrets. When deploying the application, secrets should be passed as environment variables, which can be accessed by the application at runtime. This avoids hardcoding sensitive values.

For instance, when running a container, you can define environment variables as follows:

docker run -e DATABASE_USER=myuser -e DATABASE_PASSWORD=mypassword \
  -p 80:80 my-awesome-compose-app

The application can access these variables in Python as follows:

import os

db_user = os.getenv('DATABASE_USER')
db_password = os.getenv('DATABASE_PASSWORD')

Secret Management with Docker Secrets

For applications deployed on Docker Swarm, Docker Secrets is a built-in feature that provides an efficient way to manage sensitive data. Use the following steps to create and use Docker Secrets.

  1. Create a Secret

    You can create a Docker secret by using the following command:

    echo "mypassword" | docker secret create database_password -
    
  2. Configure the Service to Use Secrets

    When defining the service in your docker-compose.yml, specify the secret like this:

    version: '3.8'
    services:
      app:
        image: my-awesome-compose-app
        secrets:
          - database_password
    
    secrets:
      database_password:
        external: true
    
  3. Accessing Secrets Inside the Container

    Inside your application, secrets will be available in /run/secrets/. You can read them directly:

    with open('/run/secrets/database_password', 'r') as f:
        db_password = f.read().strip()
    

Golang Integration with Secrets

In the nginx-golang backend, you can manage secrets during the Go build process. Ensure to add the relevant permissions to access secrets:

  • The Golang module path:
github.com/docker/awesome-compose/nginx-golang/backend

When building the Go application:

go build -o myapp .

Within the application, use environment variables or secrets through the Docker runtime as shown in the previous sections.

Ensuring No Hardcoding of Secrets

Always make certain that no sensitive information is hardcoded into the application or its dependencies. Regularly review the code and use methods like secrets management, as shown above, to uphold security standards.

Conclusion

In docker/awesome-compose, securely managing secrets in production environments can be effectively achieved using environment variables and Docker Secrets. This practice not only enhances security but also helps in maintaining clean and maintainable code.