Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.venv
Dockerfile
.idea
docker-compose.yml
Comment on lines +1 to +4
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good start for the .dockerignore file. To better align with the requirement to keep the image as thin as possible, consider adding other common patterns to this list. For example, you should ignore Python's cache directory (__pycache__/) and often the .gitignore file itself.

Comment on lines +1 to +4
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is missing some important entries. To avoid including secrets and unnecessary files in your Docker image, it's a good practice to also ignore files like .env, media, __pycache__, and .pytest_cache. This helps fulfill the requirement to make your docker images as thin as possible.

2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*.iml
.env
.DS_Store
venv/
.venv/
.pytest_cache/
**__pycache__/
**db.sqlite3
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pattern is not correct for ignoring the db.sqlite3 file. The ** glob in this context doesn't function as a recursive wildcard. To ignore the db.sqlite3 file at the root of the project, you can simply write db.sqlite3. If you want to ignore it in any subdirectory, the correct pattern would be **/db.sqlite3.

Expand Down
22 changes: 22 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
FROM python:3.12-alpine
LABEL maintainer="dmitriykuzmin@ymail.com"

ENV PYTHONUNBUFFERED=1

WORKDIR /app

COPY requirements.txt requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

COPY . .
RUN mkdir -p /files/media

RUN adduser \
--disabled-password \
--no-create-home \
my_user

RUN chown -R my_user /files/media /app
RUN chmod -R 755 /files/media/

USER my_user
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Generated by Django 5.2.12 on 2026-03-31 10:55

import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('cinema', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.AlterField(
model_name='movie',
name='actors',
field=models.ManyToManyField(blank=True, related_name='movies', to='cinema.actor'),
),
migrations.AlterField(
model_name='movie',
name='genres',
field=models.ManyToManyField(blank=True, related_name='movies', to='cinema.genre'),
),
migrations.AlterField(
model_name='moviesession',
name='cinema_hall',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='movie_sessions', to='cinema.cinemahall'),
),
migrations.AlterField(
model_name='moviesession',
name='movie',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='movie_sessions', to='cinema.movie'),
),
migrations.AlterField(
model_name='order',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='orders', to=settings.AUTH_USER_MODEL),
),
]
15 changes: 10 additions & 5 deletions cinema_service/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.0/ref/settings/
"""
import os
from datetime import timedelta
from pathlib import Path

Expand All @@ -27,7 +28,7 @@
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []
ALLOWED_HOSTS = ["0.0.0.0", "127.0.0.1", "localhost"]

INTERNAL_IPS = [
"127.0.0.1",
Expand All @@ -47,6 +48,7 @@
"debug_toolbar",
"cinema",
"user",
"core",
]

MIDDLEWARE = [
Expand Down Expand Up @@ -86,12 +88,15 @@

DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db.sqlite3",
"ENGINE": "django.db.backends.postgresql",
"NAME": os.environ.get("POSTGRES_DB"),
"USER": os.environ.get("POSTGRES_USER"),
"PASSWORD": os.environ.get("POSTGRES_PASSWORD"),
"HOST": os.environ.get("POSTGRES_HOST"),
"PORT": os.environ.get("POSTGRES_PORT"),
}
}


# Password validation
# https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators

Expand Down Expand Up @@ -134,7 +139,7 @@
STATIC_URL = "static/"

MEDIA_URL = "/media/"
MEDIA_ROOT = BASE_DIR / "media"
MEDIA_ROOT = "/files/media"

# Default primary key field type
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field
Expand Down
Empty file added core/__init__.py
Empty file.
3 changes: 3 additions & 0 deletions core/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.contrib import admin

# Register your models here.
6 changes: 6 additions & 0 deletions core/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class CoreConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "core"
Empty file added core/management/__init__.py
Empty file.
Empty file.
21 changes: 21 additions & 0 deletions core/management/commands/wait_for_db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import time

from django.db import connections
from django.db.utils import OperationalError
from django.core.management.base import BaseCommand


class Command(BaseCommand):
"""Django command to pause execution until database is available"""

def handle(self, *args, **kwargs):
self.stdout.write("Waiting for database...")
while True:
try:
db = connections["default"]
db.ensure_connection()
break
except OperationalError:
self.stdout.write("Database unavailable, waiting 1 second...")
time.sleep(1)
self.stdout.write(self.style.SUCCESS("Database available"))
Empty file added core/migrations/__init__.py
Empty file.
3 changes: 3 additions & 0 deletions core/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.db import models

# Create your models here.
3 changes: 3 additions & 0 deletions core/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.test import TestCase

# Create your tests here.
3 changes: 3 additions & 0 deletions core/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.shortcuts import render

# Create your views here.
31 changes: 31 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
services:
app:
build:
context: .
ports:
- "8000:8000"
volumes:
- ./:/app/
- my_media:/files/media
command: >
sh -c "python manage.py wait_for_db &&
python manage.py migrate &&
python manage.py runserver 0.0.0.0:8000"
env_file:
- .env
depends_on:
- db

db:
image: postgres:14-alpine
ports:
- "5432:5432"
env_file:
- .env
restart: always
volumes:
- my_db:/var/lib/postgresql/data

volumes:
my_db:
my_media:
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ djangorestframework
djangorestframework-simplejwt
drf-spectacular
Pillow
psycopg==3.1.12
psycopg-binary==3.1.12
Loading