Skip to content

Commit

Permalink
feat: add Caddy server support and configuration (#13)
Browse files Browse the repository at this point in the history
* feat: add Caddy server support and configuration

- Create a Caddyfile to serve static and media files and to forward requests to Django
- Update README.md with instructions for using Caddy as an alternative to Traefik
- Add docker-compose.caddy.yml for easy setup with Caddy, Django, and Postgres

* Update README.md
  • Loading branch information
amerkurev authored Jan 19, 2024
1 parent f1c00f1 commit 11dfc1c
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 6 deletions.
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ trim_trailing_whitespace = true
indent_style = space
indent_size = 2

[{Dockerfile,Makefile,*.Makefile,go.mod,go.sum,*.go,.gitmodules}]
[{Dockerfile,Caddyfile,Makefile,*.Makefile,go.mod,go.sum,*.go,.gitmodules}]
indent_style = tab
indent_size = 4

Expand Down
4 changes: 2 additions & 2 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ POSTGRES_DB=django_db
POSTGRES_HOST=postgres
POSTGRES_PORT=5432

GUNICORN_PORT=8000
GUNICORN_WORKERS=2
# the value is in seconds
GUNICORN_TIMEOUT=60
GUNICORN_TIMEOUT=60 # the value is in seconds
GUNICORN_LOG_LEVEL=info

# DJANGO_SECRET_KEY=
Expand Down
16 changes: 16 additions & 0 deletions Caddyfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{$MY_DOMAIN} {

handle_path /static/* {
root * /usr/share/caddy/static
file_server
}

handle_path /media/* {
root * /usr/share/caddy/media
file_server
}

handle {
reverse_proxy django:{$GUNICORN_PORT}
}
}
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ The technology stack used includes:
- [`PostgreSQL`](https://www.postgresql.org) ver. 15
- [`Gunicorn`](https://gunicorn.org) ver. 21.2
- [`Traefik`](https://traefik.io/traefik/) ver. 2.9
- [`Caddy`](https://caddyserver.com) ver. 2.7
- [`Docker`](https://docs.docker.com/get-docker/) and [`Docker Compose`](https://docs.docker.com/compose/)

Nothing extra, only the essentials! You can easily add everything else yourself by expanding the existing configuration files:
Expand All @@ -32,7 +33,7 @@ So, what do you get by using this project as a template for your project? Let's
- A well-configured Django project, with individual settings that can be changed using environment variables
- Building and debugging a Django project in Docker
- Integrated [pytest](https://docs.pytest.org) and [coverage](https://coverage.readthedocs.io) for robust testing and code quality assurance ✅
- A ready-made docker-compose file that brings together Postgres - Django - Gunicorn - Traefik
- A ready-made docker-compose file that brings together Postgres - Django - Gunicorn - Traefik (or Caddy)
- Serving static files (and user-uploaded files) with Nginx
- Automatic database migration and static file collection when starting or restarting the Django container
- Automatic creation of the first user in Django with a default login and password
Expand Down Expand Up @@ -192,6 +193,27 @@ docker compose exec django python manage.py check --deploy
docker compose exec django python manage.py shell
```

### Using Caddy Server Instead of Traefik

Traefik is a great edge router, but it doesn't serve static files, which is why we pair it with [Nginx](https://github.com/amerkurev/django-docker-template/blob/master/docker-compose.yml#L26) in our setup. If you prefer a single tool that can handle everything, you might want to try [Caddy](https://caddyserver.com).

Caddy can automatically handle the creation and renewal of Let's Encrypt certificates and also serve static files, which allows you to use just one server instead of two.

Here's how to set up Caddy with your project:

1. Ensure you have a [`Caddyfile`](Caddyfile) in your project directory. This file will tell Caddy how to deliver static and media files and how to forward other requests to your Django app.

2. Swap out the `docker-compose.yml` and `docker-compose.tls.yml` with a single [`docker-compose.caddy.yml`](docker-compose.caddy.yml). This file is designed to set up Caddy with Django and Postgres, and it doesn't include Nginx, which makes the file shorter and easier to understand.

3. To get your Django project up with Caddy, run the following command, making sure to replace `your.domain.com` with your actual domain:

```console
MY_DOMAIN=your.domain.com docker compose -f docker-compose.caddy.yml up -d
```

Choosing Caddy simplifies your setup by combining the functionalities of Traefik and Nginx into one. It's straightforward and takes care of HTTPS certificates for you automatically.
Enjoy the ease of deployment with Caddy!

## What's next?

Now that you have a working project, you can extend it as you like, adding [dashboards for monitoring service health](https://doc.traefik.io/traefik/operations/dashboard/), [centralized log collection](https://www.fluentd.org), [secret storage](https://www.vaultproject.io), and of course, your own Django applications. All of this is beyond the scope of the current description, as the idea of this project is minimalism and providing only the essentials. Good luck!
Expand Down
58 changes: 58 additions & 0 deletions docker-compose.caddy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
version: "3.9"
services:
postgres:
image: postgres:15
env_file: .env
restart: unless-stopped
volumes:
- "postgres-data:/var/lib/postgresql/data/"

django:
build: .
image: django-docker
env_file: .env
environment:
- "DJANGO_ALLOWED_HOSTS=${MY_DOMAIN}"
- "DJANGO_CSRF_TRUSTED_ORIGINS=https://${MY_DOMAIN}"
- "DJANGO_SESSION_COOKIE_SECURE=true"
- "DJANGO_CSRF_COOKIE_SECURE=true"
- "DJANGO_SECURE_SSL_REDIRECT=true"
restart: unless-stopped
volumes:
- "staticfiles-data:/var/www/static"
- "media-data:/var/www/media"
depends_on:
- postgres

caddy:
image: caddy:2.7-alpine
env_file: .env
environment:
- "MY_DOMAIN=${MY_DOMAIN}"
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- "./Caddyfile:/etc/caddy/Caddyfile:ro"
- "caddy-data:/data"
- "caddy-config:/config"
- type: volume
source: media-data
target: /usr/share/caddy/media
read_only: true
volume:
nocopy: true
- type: volume
source: staticfiles-data
target: /usr/share/caddy/static
read_only: true
volume:
nocopy: true

volumes:
caddy-data:
caddy-config:
media-data:
postgres-data:
staticfiles-data:
2 changes: 1 addition & 1 deletion docker-compose.debug.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ services:
command: ["/docker-cmd.sh", "--debug"]
volumes:
- "media-data:/var/www/media"
- "./website:/usr/src/website" # mount the source code
- "./website:/usr/src/website" # mount the source code for watching changes
depends_on:
- postgres
labels:
Expand Down
2 changes: 1 addition & 1 deletion website/polls/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class QuestionAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ['question_text']}),
('Date information', {'fields': ['pub_date'], 'classes': ['expand']}),
('Files', {'fields': ['upload'], 'classes': ['collapse']}),
('Files', {'fields': ['upload'], 'classes': ['expand']}),
]

inlines = [ChoiceInline]
Expand Down

0 comments on commit 11dfc1c

Please sign in to comment.