I have a FastAPI/Uvicorn/SQLAlchemy app that I'm trying to run in ECS. I have successfully run the app via docker compose, but when I try to deploy the container in ecs I get the following error:
executable file not found in $PATH:
I am trying to run this command:
bash -c alembic -c alembic.ini upgrade head && gunicorn --bind 0.0.0.0:8000 -k uvicorn.workers.UvicornWorker src.backend_service.main:app
I have tried this via the "command" section of the ECS UI.
My Dockerfile looks like this:
# NOTE: this image has to be built from the root directory since it contains files and folders from there
# docker build -t backend_service .
# Pull base image
FROM --platform=linux/amd64 python:3.10.11-slim-buster
# Set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
WORKDIR /code/
# Install dependencies
COPY ./src/backend_service/requirements_backend_service.txt requirements_backend_service.txt
RUN pip3 install -r requirements_backend_service.txt
COPY ./src/backend_service /code/src/backend_service/
COPY ./db_alembic /code/db_alembic
COPY ./alembic.ini /code/alembic.ini
ENV PATH="/code/venv/bin:$PATH"
ENV PATH="/code:$PATH"
ENV PYTHONPATH=/code
EXPOSE 8000
And my Docker Compose file looks like this:
backend_service:
platform: linux/amd64
environment:
ENV: dev
image: backend_service:latest
build:
dockerfile: ./Dockerfile.backend
command: bash -c "alembic -c alembic.ini upgrade head && gunicorn --bind 0.0.0.0:8000 -k uvicorn.workers.UvicornWorker src.backend_service.main:app"
volumes:
- ./src/backend_service:/code/src/backend_service
ports:
- "8000:8000"
My ecs task definition looks like this:
{
"taskDefinitionArn": "arn:aws:ecs:XXXXXXXXX:task-definition/run_backend_service_manual:3",
"containerDefinitions": [
{
"name": "backend_service",
"image": "XXXXXXXXX/ecr-repository-dev-v1:backend_service_latest",
"cpu": 0,
"portMappings": [
{
"name": "backend_service-8000-tcp",
"containerPort": 8000,
"hostPort": 8000,
"protocol": "tcp",
"appProtocol": "http"
}
],
"essential": true,
"command": [
"bash -c alembic -c alembic.ini upgrade head && gunicorn --bind 0.0.0.0:8000 -k uvicorn.workers.UvicornWorker src.backend_service.main:app"
],
"environment": [],
"environmentFiles": [],
"mountPoints": [],
"volumesFrom": [],
"workingDirectory": "/code/",
"ulimits": [],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/run_backend_service_manual",
"mode": "non-blocking",
"awslogs-create-group": "true",
"max-buffer-size": "25m",
"awslogs-region": "eu-central-1",
"awslogs-stream-prefix": "ecs"
},
"secretOptions": []
},
"systemControls": []
}
],
"family": "run_backend_service_manual",
"taskRoleArn": "arn:aws:iam::XXXXXXXXX:role/dev-ecs-execution-v1",
"executionRoleArn": "arn:aws:iam::XXXXXXXXX:role/dev-ecs-execution-v1",
"networkMode": "awsvpc",
"revision": 3,
"volumes": [],
"status": "ACTIVE",
"requiresAttributes": [
{
"name": "com.amazonaws.ecs.capability.logging-driver.awslogs"
},
{
"name": "ecs.capability.execution-role-awslogs"
},
{
"name": "com.amazonaws.ecs.capability.ecr-auth"
},
{
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.19"
},
{
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.17"
},
{
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.28"
},
{
"name": "com.amazonaws.ecs.capability.task-iam-role"
},
{
"name": "ecs.capability.execution-role-ecr-pull"
},
{
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.18"
},
{
"name": "ecs.capability.task-eni"
},
{
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.29"
}
],
"placementConstraints": [],
"compatibilities": [
"EC2",
"FARGATE"
],
"requiresCompatibilities": [
"FARGATE"
],
"cpu": "1024",
"memory": "2048",
"runtimePlatform": {
"cpuArchitecture": "X86_64",
"operatingSystemFamily": "LINUX"
},
"registeredAt": "2024-12-31T19:56:03.600Z",
"registeredBy": "arn:aws:iam::XXXXXXXXX:root",
"enableFaultInjection": false,
"tags": []
}
I think this might have something to do with how I'm passing the command because it works via Docker Compose. I have tried the docker run documentation and have tried putting the parameters in a list (["paramq1", "param2"]) but I keep getting the same error.
What might I be doing wrong?
run.shto your docker image, that has the actual command inside of it, and then all you have to do is have ECS run the script."command": ["bash", "-c", "alembic ... && gunicorn ..."]work (only three parts)? And is your error message complete (does it really end after the colon)?