Skip to content

Solution#1009

Open
Viktor395 wants to merge 3 commits into
mate-academy:masterfrom
Viktor395:develop
Open

Solution#1009
Viktor395 wants to merge 3 commits into
mate-academy:masterfrom
Viktor395:develop

Conversation

@Viktor395
Copy link
Copy Markdown

No description provided.

Copy link
Copy Markdown

@mateacademy-ai-mentor mateacademy-ai-mentor left a comment

Choose a reason for hiding this comment

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

Review Summary

Changes are needed before this can be accepted, mainly around the Docker/PostgreSQL integration and startup behavior.

Critical issues that must be fixed (blockers):

  1. In cinema_service/settings.py, the DATABASES block (currently using ENGINE: 'django.db.backends.sqlite3') still points to SQLite; this prevents the app from using the PostgreSQL container. Replace it with a PostgreSQL configuration (ENGINE: 'django.db.backends.postgresql') that reads DB_HOST, DB_NAME, DB_USER, DB_PASS, and optional DB_PORT (default 5432) from environment variables so Django connects to the db service defined in docker-compose.yml.
  2. In the same settings file, ALLOWED_HOSTS is an empty list and STATIC_ROOT is missing; this will cause host header issues once DEBUG is off and will break collectstatic/static serving in Docker. Add at least ['127.0.0.1', 'localhost'] (or read from an env var) to ALLOWED_HOSTS and define STATIC_ROOT = BASE_DIR / 'staticfiles', ensuring it matches any static volume you configure in Docker.
  3. In core/management/commands/wait_for_db.py, the loop only accesses connections['default'] but never actually opens a connection, so it may report the DB as ready when PostgreSQL is still starting. Inside the try block, explicitly call something like connections['default'].cursor() or connections['default'].ensure_connection() so an OperationalError is raised until the database is truly available.

Important but non-blocking improvements:

  • In docker-compose.yml, avoid relying on the .:/app bind mount for a self-contained deployment; instead, bake the code into the image and keep the mount only for local development if needed.
  • Also in docker-compose.yml, add named volumes for media and static files (for example, media_data:/app/media and static_data:/app/staticfiles) and consider moving database credentials into an .env file or secrets mechanism rather than hardcoding them.
    Once you address the PostgreSQL settings, wait_for_db connection attempt, and static/host configuration, your Dockerized setup will satisfy the functional requirements and the rest will be solid refinements of an otherwise good structure.

✨ Please rate this review in the Platform's notification center1. I will be grateful for your feedback! ✨

Important

Fix the issues, commit the changes, and then re-request my review using the Re-request review button2 in the Reviewers tab.

Tip

If you have any comments about this review, please leave a message in the Add a comment section below and mention me with the @mateacademy-ai-mentor tag3.
I will read your message during my next review of your pull request. Please do not reply directly to my comments, as that feature is not supported yet.

Caution

Do not close the pull request until the review is complete. Closing it early can lead to unexpected behavior and disrupt the review process.

Footnotes

  1. Rate AI review example

  2. Re-request AI review example

  3. Add AI review comments example

"debug_toolbar",
"cinema",
"user",
"core",
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 still uses SQLite (see DATABASES block) which prevents the app from using the PostgreSQL service defined in docker-compose. Update DATABASES to use the PostgreSQL engine (django.db.backends.postgresql) and read connection parameters from environment variables (DB_HOST, DB_NAME, DB_USER, DB_PASS, optional DB_PORT default 5432) so the app connects to the db container. Also set ALLOWED_HOSTS to include the host(s) you will access (e.g. ['127.0.0.1', 'localhost'] or ['*'] for dev) so runserver 0.0.0.0:8000 is accessible. Finally, add STATIC_ROOT (for example: STATIC_ROOT = BASE_DIR / 'staticfiles') so you can run collectstatic and serve static files from a volume in Docker; MEDIA_ROOT is present but confirm it matches your docker volumes. Optionally, consider sourcing SECRET_KEY and DEBUG from environment variables for better Docker practice.

Comment thread core/management/commands/wait_for_db.py Outdated
Comment on lines +13 to +14
try:
db_conn = connections['default']
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The command does not actually attempt a DB connection. Accessing connections['default'] alone does not necessarily raise an OperationalError if the DB is down. Use connections['default'].cursor() or connections['default'].ensure_connection() inside the try block to attempt a real connection so the loop correctly waits until PostgreSQL is ready.

Comment on lines +12 to +17
while not db_conn:
try:
db_conn = connections['default']
except OperationalError:
self.stdout.write('Database unavailable, waiting 1 second...')
time.sleep(1)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Consider limiting the retry behavior or adding a timeout/logging: currently this loops indefinitely with 1s sleeps. That's acceptable for many setups, but you may want to surface a clear error after N attempts for easier debugging.

Comment on lines +5 to +8

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

docker-compose defines postgres but does not expose a DB port to the host (not necessary for container-to-container comms) — fine. However ensure your Django settings read the DB env vars defined below (DB_HOST, DB_NAME, DB_USER, DB_PASS) so the app will actually connect to this postgres service.

Comment thread core/management/commands/wait_for_db.py Outdated
Comment on lines +18 to +19

self.stdout.write(self.style.SUCCESS('Database available!')) No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The app service mounts the project directory into /app (- .:/app). Your Dockerfile switches to a non-root user (django-user), which can cause permission problems when the container user UID does not match the host file ownership. Either run as root during development, adjust ownership in the image (chown) before switching users, or document required permissions to avoid permission errors at runtime.

Comment thread docker-compose.yml
Comment on lines +15 to +17
sh -c "python manage.py wait_for_db &&
python manage.py migrate &&
python manage.py runserver 0.0.0.0:8000"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Good: the app command runs python manage.py wait_for_db before migrations and starting the server, which ensures the service will wait for the DB rather than fail on startup.

Comment thread docker-compose.yml
python manage.py migrate &&
python manage.py runserver 0.0.0.0:8000"
volumes:
- .:/app
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The app service bind-mounts the project directory from the host (- .:/app). That makes the container depend on local files and breaks the requirement that Docker alone should be sufficient. For a self-contained deployment, avoid bind mounts so the image includes the code (or make mounts optional for development only).

Comment thread docker-compose.yml
Comment on lines +18 to +21
volumes:
- .:/app
ports:
- "8000:8000"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

There is no named volume for media/static files. Add volumes for media/ (and use STATIC_ROOT + collectstatic) so media and static can persist in Docker, for example a named volume like - media_data:/app/media and - static_data:/app/staticfiles.

Comment thread docker-compose.yml
environment:
POSTGRES_DB: cinema_db
POSTGRES_USER: cinema_user
POSTGRES_PASSWORD: secretpassword
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

You expose DB credentials directly in the compose file (POSTGRES_PASSWORD for the db and DB_PASS for the app). Avoid hardcoding secrets in the repository; consider using an .env file (kept out of VCS), Docker secrets, or CI/CD injection instead.

Comment thread docker-compose.yml
Comment on lines +23 to +26
- DB_HOST=db
- DB_NAME=cinema_db
- DB_USER=cinema_user
- DB_PASS=secretpassword
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The app receives DB environment variables (DB_HOST, DB_NAME, DB_USER, DB_PASS). Ensure your Django settings actually read these variables and configure the PostgreSQL backend accordingly; otherwise the app will not connect to the postgres service at runtime.

Copy link
Copy Markdown

@mateacademy-ai-mentor mateacademy-ai-mentor left a comment

Choose a reason for hiding this comment

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

Review Summary

Your solution is approved because it implements all core Dockerization requirements: the Dockerfile builds a working Django + PostgreSQL image with a non-root user, docker-compose.yml brings up app and db with a wait_for_db management command, and Django is correctly configured via environment variables for the Postgres database, STATIC_ROOT, and ALLOWED_HOSTS.

There are a few non-blocking improvements you could make next. In the Dockerfile, consider adding --no-install-recommends to the apt-get install line and either removing build-time packages (gcc, libpq-dev) after pip install or switching to psycopg2-binary to keep the final image smaller; also prefer COPY --chown=django-user:django-user . . so you can drop the expensive recursive chown -R layer. In docker-compose.yml, the app service currently uses a bind mount .:/app in volumes, which is great for local development but prevents the image from being fully self-contained; for a more production-like setup, move that mount to a separate dev override file or remove it in your main compose. Also in docker-compose.yml, the hardcoded POSTGRES_USER, POSTGRES_PASSWORD, and related DB_* variables in the environment sections should ideally be moved to an .env file or secrets for safer credential handling. As an enhancement, you can add restart: unless-stopped and simple healthcheck definitions for app and db so that containers are automatically restarted and their readiness is visible to orchestration tools.

Overall, you met the functional checklist items well, and these suggestions are about making your images thinner and your deployment more production-ready, which is a strong next step in your learning.


✨ Please rate this review in the Platform's notification center1. I will be grateful for your feedback! ✨

Footnotes

  1. Rate AI review example

Comment thread .gitignore
.gitignore
__pycache__
*.pyc
db.sqlite3 No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Rather than copying the whole repo and then running chown -R, consider using COPY --chown=django-user:django-user . . so ownership is set at copy time and you can remove the expensive chown -R step (makes the image build faster and layer-smaller). Also ensure your .dockerignore excludes development artifacts (you have one, good).

Comment thread .gitignore
media
.venv
.git
.gitignore
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

If your requirements include psycopg2, consider using psycopg2-binary to avoid the need for gcc/libpq-dev at build time, or use a multi-stage build where build dependencies are removed in the final image. This helps keep the runtime image small.

Comment thread Dockerfile
Comment on lines +7 to +10
RUN apt-get update && apt-get install -y \
gcc \
libpq-dev \
&& rm -rf /var/lib/apt/lists/*
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Add --no-install-recommends to the apt-get install command (and consider cleaning up build-time packages after pip install or using a multi-stage build). This reduces image size by avoiding unnecessary recommended packages and allows you to remove build dependencies (gcc/libpq-dev) after they are no longer needed.

Comment thread Dockerfile
RUN pip install --no-cache-dir -r requirements.txt


COPY . .
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

COPY . . will copy all files and then you run a chown later. Prefer using the COPY --chown=django-user:django-user form to set ownership during copy (or create the user before COPY), which avoids an expensive recursive chown at build time.

Comment thread Dockerfile
RUN adduser --disabled-password --no-create-home django-user


RUN chown -R django-user:django-user /app
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The explicit recursive chown is expensive and can be avoided if you use COPY --chown or if the user is created before copying files. Consider removing this step after changing COPY to set ownership.

Comment thread docker-compose.yml
Comment on lines +31 to +32
depends_on:
- db
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

depends_on ensures service start order but does not wait for the DB to be ready; your command runs wait_for_db which addresses this. As an enhancement you can also add a short healthcheck for the db service so orchestration and tools can detect readiness more explicitly.

except OperationalError:
self.stdout.write('Database unavailable, waiting 1 second...')
time.sleep(1)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

For production deployments avoid bind-mounting the project source into the container (the .:/app mount). Baking code into the image makes the deployment self-contained; keep bind mounts only for local development to allow live code edits.

Comment on lines +7 to +10
"""Django command to pause execution until database is available"""

def handle(self, *args, **options):
self.stdout.write('Waiting for database...')
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The apt-get install line should use --no-install-recommends to avoid pulling unnecessary packages. Also consider removing build-time packages after pip install or use a multi-stage build (or psycopg[binary]) to keep the final image thin.

try:
connection = connections['default']
connection.cursor()
db_conn = True
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

You COPY the entire project and then run a recursive chown -R, which creates an extra expensive layer. Prefer creating the user before COPY and use COPY --chown=django-user:django-user . . to set ownership during copy and avoid the chown step.

Comment on lines +31 to 32
ALLOWED_HOSTS = os.environ.get("ALLOWED_HOSTS", "127.0.0.1,localhost").split(",")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

depends_on only controls start order and does not guarantee the DB is ready. You already run wait_for_db in the app command which is good; as an improvement consider adding a healthcheck for the db service and using depends_on: condition: service_healthy (Compose v3.4+) so Compose can reason about service health explicitly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants