| """Task 2: Dockerfile Runtime Errors — MEDIUM. |
| |
| Agent fixes Dockerfiles that build successfully but fail at container |
| runtime: missing WORKDIR, CMD/ENTRYPOINT conflicts, permission issues, |
| and missing environment variables. |
| """ |
|
|
|
|
|
|
| from server.models import TaskDifficulty |
| from server.tasks.base import BaseTask |
|
|
|
|
| class DockerfileRuntimeTask(BaseTask): |
| NAME = "Dockerfile Runtime Errors" |
| DESCRIPTION = "Fix runtime/container execution issues in Dockerfiles" |
| DIFFICULTY = TaskDifficulty.MEDIUM |
| AVAILABLE_SECRETS = [] |
|
|
| SCENARIOS = [ |
| |
| { |
| "id": "missing_workdir", |
| "files": [ |
| { |
| "path": "Dockerfile", |
| "type": "dockerfile", |
| "content": ( |
| "FROM node:18-alpine\n" |
| "COPY package*.json ./\n" |
| "RUN npm ci\n" |
| "COPY . .\n" |
| 'CMD ["npm", "start"]' |
| ), |
| }, |
| { |
| "path": "package.json", |
| "type": "other", |
| "content": '{"name": "app", "scripts": {"start": "node index.js"}}', |
| }, |
| ], |
| "error": { |
| "phase": "docker_run", |
| "message": "Error: Cannot find module '/package.json'", |
| "exit_code": 1, |
| "failed_step": "npm start", |
| }, |
| "expected_fixes": [ |
| { |
| "file": "Dockerfile", |
| "type": "contains", |
| "expected": "WORKDIR /app", |
| "hint": "Set a working directory before COPY/RUN so files land in /app, not /", |
| } |
| ], |
| }, |
|
|
| |
| { |
| "id": "cmd_entrypoint_conflict", |
| "files": [ |
| { |
| "path": "Dockerfile", |
| "type": "dockerfile", |
| "content": ( |
| "FROM python:3.11-slim\n" |
| "WORKDIR /app\n" |
| "COPY . .\n" |
| "RUN pip install -r requirements.txt\n" |
| 'ENTRYPOINT ["python", "server.py"]\n' |
| 'CMD ["python", "server.py"]' |
| ), |
| }, |
| { |
| "path": "requirements.txt", |
| "type": "requirements", |
| "content": "flask==2.3.0", |
| }, |
| ], |
| "error": { |
| "phase": "docker_run", |
| "message": ( |
| "container exits immediately; process started twice — " |
| "ENTRYPOINT and CMD both specify the full command" |
| ), |
| "exit_code": 1, |
| "failed_step": "container start", |
| }, |
| "expected_fixes": [ |
| { |
| "file": "Dockerfile", |
| "type": "not_contains", |
| "expected": 'CMD ["python", "server.py"]', |
| "hint": ( |
| "When using ENTRYPOINT as a full command, CMD should provide " |
| "default arguments only, or be removed entirely" |
| ), |
| } |
| ], |
| }, |
|
|
| |
| { |
| "id": "entrypoint_not_executable", |
| "files": [ |
| { |
| "path": "Dockerfile", |
| "type": "dockerfile", |
| "content": ( |
| "FROM python:3.11-slim\n" |
| "WORKDIR /app\n" |
| "COPY . .\n" |
| "RUN pip install -r requirements.txt\n" |
| 'ENTRYPOINT ["./start.sh"]' |
| ), |
| }, |
| { |
| "path": "requirements.txt", |
| "type": "requirements", |
| "content": "flask==2.3.0", |
| }, |
| { |
| "path": "start.sh", |
| "type": "other", |
| "content": "#!/bin/bash\npython app.py", |
| }, |
| ], |
| "error": { |
| "phase": "docker_run", |
| "message": "exec ./start.sh: permission denied", |
| "exit_code": 126, |
| "failed_step": "ENTRYPOINT ./start.sh", |
| }, |
| "expected_fixes": [ |
| { |
| "file": "Dockerfile", |
| "type": "contains", |
| "expected": "RUN chmod +x ./start.sh", |
| "hint": "The entrypoint script must be made executable with chmod +x before the ENTRYPOINT instruction", |
| } |
| ], |
| }, |
|
|
| |
| { |
| "id": "missing_required_env", |
| "files": [ |
| { |
| "path": "Dockerfile", |
| "type": "dockerfile", |
| "content": ( |
| "FROM python:3.11-slim\n" |
| "WORKDIR /app\n" |
| "COPY . .\n" |
| "RUN pip install -r requirements.txt\n" |
| "EXPOSE 8080\n" |
| 'CMD ["python", "app.py"]' |
| ), |
| }, |
| { |
| "path": "requirements.txt", |
| "type": "requirements", |
| "content": "flask==2.3.0\ngunicorn==21.2.0", |
| }, |
| ], |
| "error": { |
| "phase": "docker_run", |
| "message": ( |
| "KeyError: 'DATABASE_URL'\n" |
| "Application requires DATABASE_URL environment variable to be set" |
| ), |
| "exit_code": 1, |
| "failed_step": "python app.py", |
| }, |
| "expected_fixes": [ |
| { |
| "file": "Dockerfile", |
| "type": "contains", |
| "expected": "ENV DATABASE_URL", |
| "hint": "Add an ENV instruction to set DATABASE_URL (use a default or placeholder value)", |
| } |
| ], |
| }, |
|
|
| |
| { |
| "id": "non_root_privileged_port", |
| "files": [ |
| { |
| "path": "Dockerfile", |
| "type": "dockerfile", |
| "content": ( |
| "FROM python:3.11-slim\n" |
| "WORKDIR /app\n" |
| "COPY . .\n" |
| "RUN pip install -r requirements.txt\n" |
| "RUN useradd --create-home appuser\n" |
| "USER appuser\n" |
| "EXPOSE 80\n" |
| 'CMD ["python", "app.py"]' |
| ), |
| }, |
| { |
| "path": "requirements.txt", |
| "type": "requirements", |
| "content": "flask==2.3.0", |
| }, |
| ], |
| "error": { |
| "phase": "docker_run", |
| "message": ( |
| "PermissionError: [Errno 13] Permission denied — " |
| "non-root user cannot bind to port 80" |
| ), |
| "exit_code": 1, |
| "failed_step": "python app.py", |
| }, |
| "expected_fixes": [ |
| { |
| "file": "Dockerfile", |
| "type": "contains", |
| "expected": "EXPOSE 8080", |
| "hint": "Non-root users cannot bind to ports below 1024 — use a higher port like 8080", |
| } |
| ], |
| }, |
| ] |
|
|