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*