I tend to use PaaS solutions like Heroku or Next.JS when deploying my apps, but in some cases I need more fine-tuned control over my servers. This is the case for some of my projects that require local LLMs, FFMPEG, or Whisper to be installed locally. Docker also allows way more control over detailed server configuration, such as the ability to set response timeouts that greatly exceed the 90 seconds of Heroku or 100 seconds of DigitalOcean Apps. # Installing Docker 1. [Download](https://www.docker.com/products/docker-desktop/) and install Docker 2. Install docker CLI using `brew install docker` 3. Verify that docker is installed and can connect to the Daemon by entering `docker info`. You should get a result with the docker version and the server details # Creating a Docker container for a Django projet These instructions will be oriented around my main usage, which is a simple container running a Django Python app managed via Poetry 1. Set up an empty `Dockerfile` 2. Define the parent image you wish to use ``` # Use an official Python runtime as a parent image FROM python:3.11.6 ``` 3. Set up environment variables ``` # Set environment variables ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONUNBUFFERED 1 ``` 4. Install poetry and configure it to install the app's dependencies ``` # Install Poetry RUN pip install poetry # Set the working directory in the container WORKDIR /app # Copy only the dependencies file to optimize Docker caching COPY poetry.lock pyproject.toml /app/ # Install dependencies # RUN source $HOME/.poetry/env && poetry update && poetry install RUN poetry install --no-root --no-interaction ``` 5. Copy the rest of the application over to the app folder ``` # Copy the rest of the application code COPY . /app/ ``` 6. Initialize the Django server ``` # Expose the port Gunicorn will listen on EXPOSE 8000 # Run Gunicorn CMD ["poetry", "run", "gunicorn", "--bind", "0.0.0.0:8000", "your_project_name.wsgi:application"] ``` *Note: Docker seems broken on my mac at the moment - cannot seem to connect to the server running inside the docker instance. Going to use bare metal setup for now, but will revisit docker setup down the road*