DEV Community

Cover image for Docker for Absolute Beginners — Part 7
Md Enayetur Rahman
Md Enayetur Rahman

Posted on

Docker for Absolute Beginners — Part 7

How Your Host Browser Talks to a Django Container

In Part 6 we mastered serving a Vite front-end and talking to the outside world. Now let’s flip things around: run a Django backend in Docker and hit its API from your laptop, Postman, or browser using localhost. You’ll see how port binding bridges the gap between your container and your desktop — and how to use Docker Compose for fast, modern Django dev!


Learning Aims

By the end of this post you will be able to:

  1. Understand how Docker connects containerized apps to your laptop via localhost.

  2. Use Docker Compose to manage Django development with hot reload, environment variables, and dependency isolation.

  3. See how a simple CRUD API in Django can be tested from any desktop HTTP client — just as if it was running natively.

1. Project Overview

Your folder structure:

docker-container-to-localhost/
├─ Dockerfile
├─ docker-compose.yml
├─ requirements.txt
├─ .env
├─ manage.py
├─ todo_proj/
└─ todos/

Enter fullscreen mode Exit fullscreen mode

The core: a Django backend serving an in-memory todo API at /todos/.

2. Docker Concepts to Learn

Dockerfile: Django, the Right Way

FROM python:3.12-slim

WORKDIR /usr/src/app

COPY requirements.txt ./
RUN pip install --upgrade pip && pip install -r requirements.txt

COPY . .

EXPOSE 8000

CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
Enter fullscreen mode Exit fullscreen mode

A Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image.

Command Description
FROM python:3.12-slim This sets the base image for our container. We are using the official Python 3.12 slim image, which is a lightweight version of Python.
WORKDIR /usr/src/app This sets the working directory inside the container to /usr/src/app. All subsequent commands will be run from this directory.
COPY requirements.txt ./ This copies the requirements.txt file from our local machine to the current working directory (/usr/src/app) inside the container.
RUN pip install --upgrade pip && pip install -r requirements.txt This command first upgrades pip to the latest version and then installs all the Python dependencies listed in the requirements.txt file.
COPY . . This copies the rest of our project's code from our local machine to the current working directory (/usr/src/app) inside the container.
EXPOSE 8000 This informs Docker that the container will listen on port 8000 at runtime.
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"] This specifies the command to run when the container starts. It will start the Django development server and make it accessible from outside the container.

docker-compose.yml

version: "3.9"

services:
  api:
    build: .
    container_name: docker-container-to-localhost
    env_file: .env
    command: python manage.py runserver 0.0.0.0:8000
    ports:
      - "${HOST_PORT}:8000"          # Host:Container
    volumes:
      - .:/usr/src/app               # Live code reload
      - /usr/local/lib/python3.12/site-packages  # Anonymous deps cache
    stdin_open: true
    tty: true
Enter fullscreen mode Exit fullscreen mode

docker-compose.yml is a YAML file that defines how Docker containers should be created, configured, and linked together.

Command Description
version: "3.9" This specifies the version of the Docker Compose file format we are using.
services: This is where we define the different services (containers) that make up our application.
api: This is the name of our service. We can name it anything we want.
build: . This tells Docker Compose to build the image for this service using the Dockerfile in the current directory.
container_name: docker-container-to-localhost This sets a custom name for our container.
env_file: .env This tells Docker Compose to load environment variables from a file named .env in the current directory.
command: python manage.py runserver 0.0.0.0:8000 This overrides the default command in the Dockerfile.
ports: This maps ports between the host machine and the container.
- "${HOST_PORT}:8000" This maps the port specified by the HOST_PORT environment variable on the host machine to port 8000 on the container.
volumes: This mounts host paths or named volumes, specified as sub-options to a service.
- .:/usr/src/app This mounts the current directory on the host machine to /usr/src/app in the container. This is great for development as changes to your code on the host will be reflected in the container.
- /usr/local/lib/python3.12/site-packages This creates an anonymous volume to cache the installed python packages.
stdin_open: true This is equivalent to the -i flag in the docker run command. It keeps STDIN open even if not attached.
tty: true This is equivalent to the -t flag in the docker run command. It allocates a pseudo-TTY.

3. How to Run and Test the Project

To run and test the project, you will need to have Docker and Docker Compose installed on your machine.

  1. Build and run the container:

    docker-compose up -d --build
    
*   `docker-compose`: The command to run Docker Compose.
*   `up`: This command builds, (re)creates, starts, and attaches to containers for a service.
*   `-d`: This runs the containers in detached mode, meaning they will run in the background.
*   `--build`: This forces Docker Compose to build the image before starting the containers.
Enter fullscreen mode Exit fullscreen mode
  1. Create the database schema:

    docker-compose exec api python manage.py migrate
    
*   `docker-compose exec`: This command executes a command in a running container.
*   `api`: The name of the service (container) we want to run the command in.
*   `python manage.py migrate`: The command to create the database schema.
Enter fullscreen mode Exit fullscreen mode
  1. Create a superuser to access the admin panel:

    docker-compose exec api python manage.py createsuperuser
    
*   Follow the prompts to create a username, email, and password.
Enter fullscreen mode Exit fullscreen mode
  1. Test the application:
*   Open your web browser and go to http://localhost:8000 (or the port you specified in your .env file). You should see the Django welcome page.

  • Go to http://localhost:8000/admin and log in with the superuser credentials you just created. You should be able to access the Django admin panel.
  • Go to http://localhost:8000/todos
    • GET -> See all todos
    • POST -> Create a new todo
    • PUT -> Update a todo
    • DELETE -> Delete a todo
Enter fullscreen mode Exit fullscreen mode

  • Why This Pattern?
    • Port binding (HOST:CONTAINER) is how you connect containers to your real desktop world. This is true for front-ends, APIs, and databases.

    • No need for localhost hacks — Docker does the network translation for you!

    • Best practice for teams — Everyone runs the same isolated dev stack, with no Python/Node install headaches.

    5. Conclusion

    From this project, you have learned:

    ✅ How to bind a container’s internal port to your computer’s localhost
    ✅ That 0.0.0.0 in your app tells it to listen for external connections
    ✅ Compose lets you manage all this with a simple, readable YAML
    ✅ Hot reload, isolated dependencies, interactive shells, and easy config — all standard!

    This project provides a solid foundation for using Docker in your Python projects. You can now explore more advanced topics like using Docker for production deployments, multi-container applications, and more.

    Top comments (0)