How do I keep dotenv secrets in Docker?

Viewed 598

I have a local dev. environment, where I connect to a SQL DB using SQLAlchemy. I do the following to get secrets from .env:

import os
from urllib.parse import quote_plus

import sqlalchemy as sa
from dotenv import load_dotenv
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

load_dotenv()


SERVER = os.getenv("SERVER_NAME")
DATABASE = os.getenv("DB_NAME")
USERNAME = os.getenv("USERNAME")
PASSWORD = os.getenv("PASSWORD")
PORT = os.getenv("PORT", default=1433)
DRIVER = os.getenv("DRIVER")

# connect using parsed URL
odbc_str = 'DRIVER='+DRIVER+';SERVER='+SERVER+';PORT='+PORT + \
    ';DATABASE='+DATABASE+';UID='+USERNAME+';PWD='+PASSWORD
connect_str = 'mssql+pyodbc:///?odbc_connect=' + quote_plus(odbc_str)
# connect with sa url format
sa_url = f"mssql+pyodbc://{USERNAME}:{PASSWORD}@{SERVER}:{PORT}/{DATABASE}?driver={DRIVER}"

SQLALCHEMY_DATABASE_URL = connect_str

engine = create_engine(SQLALCHEMY_DATABASE_URL, echo=True, future=True)
SessionLocal = sessionmaker(
    autocommit=False, autoflush=False, bind=engine, future=True)

Base = declarative_base()

When I run my app in a container, it fails, since the secret variables are None. Can I add my .env file to my container, and if so how?

My Dockerfile:

FROM python:3.8-slim-buster

EXPOSE 8000

# Keeps Python from generating .pyc files in the container
ENV PYTHONDONTWRITEBYTECODE=1

# Turns off buffering for easier container logging
ENV PYTHONUNBUFFERED=1

# build variables.
ENV DEBIAN_FRONTEND noninteractive

# install Microsoft SQL Server requirements.
ENV ACCEPT_EULA=Y
RUN apt-get update -y && apt-get update \
  && apt-get install -y --no-install-recommends curl gcc g++ gnupg unixodbc-dev

# Add SQL Server ODBC Driver 17 for Ubuntu 18.04
RUN curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - \
  && curl https://packages.microsoft.com/config/debian/10/prod.list > /etc/apt/sources.list.d/mssql-release.list \
  && apt-get update \
  && apt-get install -y --no-install-recommends --allow-unauthenticated msodbcsql17 mssql-tools \
  && echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bash_profile \
  && echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bashrc


# Install pip requirements
COPY requirements.txt .
RUN python -m pip install -r requirements.txt

WORKDIR /app
COPY . /app

# Creates a non-root user with an explicit UID and adds permission to access the /app folder
# For more info, please refer to https://aka.ms/vscode-docker-python-configure-containers
RUN adduser -u 5678 --disabled-password --gecos "" appuser && chown -R appuser /app
USER appuser



# During debugging, this entry point will be overridden. 
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "-k", "uvicorn.workers.UvicornWorker", "main:app"]

I've already looked at the Docker Secrets documentation, but I'm not really sure how to do it.

1 Answers

You don't keep them inside the image. Instead, you pass the contents of the envfile in to the docker run command from the outside.

docker run --env-file=.env my-container

You can also pass in the environment variables separately:

docker run -e SERVER_NAME=... my-container

(You could also use -v to mount in an envfile, but there's really no point when you can do the above.)

Related