ECS Bind Mount permission errors on SonarQube container

0

I am trying to deploy sonarqube on ECS but have been receiving an "AccessDeniedException" on my /opt/sonarqube/data/es7 directory. When run locally on my C9 instance the container works, and a directory listing shows everything as owned by the sonarqube user. When I deploy to ECS however I get the permission denied error and some appear to have been switched back to root ownership.

When deploying without the bind-mounted volumes the container will deploy, but I cannot see the environmental variables, which are needed to and RDS connection. I'm not sure if this is related.

What am I missing?

Troubleshooting:

  • Tried chmoding directories via the Command section in ContainerDefinitions, and received "permissions denied" on the chmod command. I've also tried setting "Privileged" to "True" to no effect.
  • Modified the sonarqube DockerFile according to the bind-mount documentation: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/bind-mounts.html. I may have not done this properly and will include the dockerfile.
  • Removing the bind mounts allows the container to deploy, but it loses its state when the task restarts and will not import environmental variable.s

My Dockerfile and JSON task definition are below. The dockerfile was pulled and modified from the Sonarqube github (the stock file does not work on ECS)

Docker file:

FROM public.ecr.aws/amazonlinux/amazonlinux:latest
RUN yum install -y shadow-utils && yum clean all
RUN useradd sonarqube
RUN mkdir -p /opt/sonarqube/data && chown sonarqube:sonarqube /opt/sonarqube/data
RUN mkdir -p /opt/sonarqube/extensions && chown sonarqube:sonarqube /opt/sonarqube/extensions
USER sonarqube
VOLUME ["/opt/sonarqube/data"]
VOLUME ["/opt/sonarqube/extensions"]

FROM eclipse-temurin:17-jre

LABEL org.opencontainers.image.url=https://github.com/SonarSource/sonar-scanner-cli-docker


RUN set eux; \

    groupadd --system --gid 1000 sonarqube; \
    useradd --system --uid 1000 --gid sonarqube sonarqube;
    #mkdir -p /opt/sonarqube/data && chown sonarqube:sonarqube /opt/sonarqube/data; \
    #mkdir -p /opt/sonarqube/extensions && chown sonarqube:sonarqube /opt/sonarqube/extensions; \
    #mkdir -p /opt/sonarqube/lib chown sonarqube:sonarqub/opt/sonarqube/lib; \
    #mkdir -p /opt/sonarqube/logs && chown sonarqube:sonarqube /opt/sonarqube/logs; \
    #mkdir -p /opt/sonarqube/temp && chown sonarqube:sonarqube /opt/sonarqube/temp; 


ENV LANG='en_US.UTF-8' \
    LANGUAGE='en_US:en' \
    LC_ALL='en_US.UTF-8'

#FROM public.ecr.aws/amazonlinux/amazonlinux:latest
#RUN yum install -y shadow-utils && yum clean all
#RUN  set -eux; \
    

#
# SonarQube setup
#
ARG SONARQUBE_VERSION=9.9.0.65466
ARG SONARQUBE_ZIP_URL=https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-${SONARQUBE_VERSION}.zip
ENV JAVA_HOME='/opt/java/openjdk' \
    SONARQUBE_HOME=/opt/sonarqube \
    SONAR_VERSION="${SONARQUBE_VERSION}" \
    SQ_DATA_DIR="/opt/sonarqube/data" \
    SQ_EXTENSIONS_DIR="/opt/sonarqube/extensions" \
    SQ_LOGS_DIR="/opt/sonarqube/logs" \
    SQ_TEMP_DIR="/opt/sonarqube/temp"
    
RUN set -eux; \
    #groupadd --system --gid 1000 sonarqube; \
    #useradd --system --uid 1000 --gid sonarqube sonarqube; \
    whoami; \
    apt-get update; \
    apt-get install -y gnupg unzip curl bash fonts-dejavu; \
    echo "networkaddress.cache.ttl=5" >> "${JAVA_HOME}/conf/security/java.security"; \
    sed --in-place --expression="s?securerandom.source=file:/dev/random?securerandom.source=file:/dev/urandom?g" "${JAVA_HOME}/conf/security/java.security"; \
    # pub   2048R/D26468DE 2015-05-25
    #       Key fingerprint = F118 2E81 C792 9289 21DB  CAB4 CFCA 4A29 D264 68DE
    # uid                  sonarsource_deployer (Sonarsource Deployer) <infra@sonarsource.com>
    # sub   2048R/06855C1D 2015-05-25
    for server in $(shuf -e hkps://keys.openpgp.org \
                            hkps://keyserver.ubuntu.com) ; do \
        gpg --batch --keyserver "${server}" --recv-keys 679F1EE92B19609DE816FDE81DB198F93525EC1A && break || : ; \
    done; \
    mkdir --parents /opt; \
    cd /opt; \
    curl --fail --location --output sonarqube.zip --silent --show-error "${SONARQUBE_ZIP_URL}"; \
    curl --fail --location --output sonarqube.zip.asc --silent --show-error "${SONARQUBE_ZIP_URL}.asc"; \
    gpg --batch --verify sonarqube.zip.asc sonarqube.zip; \
    unzip -q sonarqube.zip; \
    mv "sonarqube-${SONARQUBE_VERSION}" sonarqube; \
    rm sonarqube.zip*; \
    rm -rf ${SONARQUBE_HOME}/bin/*; \
    ln -s "${SONARQUBE_HOME}/lib/sonar-application-${SONARQUBE_VERSION}.jar" "${SONARQUBE_HOME}/lib/sonarqube.jar"; \
    chmod -R 555 ${SONARQUBE_HOME}; \
    chmod -R ugo+wrX "${SQ_DATA_DIR}" "${SQ_EXTENSIONS_DIR}" "${SQ_LOGS_DIR}" "${SQ_TEMP_DIR}"; \
    apt-get remove -y gnupg unzip curl; \
    rm -rf /var/lib/apt/lists/*;

COPY entrypoint.sh ${SONARQUBE_HOME}/docker/

WORKDIR ${SONARQUBE_HOME}
EXPOSE 9000

USER sonarqube

STOPSIGNAL SIGINT

ENTRYPOINT ["/opt/sonarqube/docker/entrypoint.sh"]

JSON Task Definition

{
    "taskDefinitionArn": "arn:aws:ecs:us-east-1:ACCOUNT:task-definition/sonar-task-def2:20",
    "containerDefinitions": [
        {
            "name": "sonarqube",
            "image": "ACCOUNT.dkr.ecr.us-east-1.amazonaws.com/sonarqube:repost",
            "cpu": 0,
            "links": [],
            "portMappings": [
                {
                    "containerPort": 9000,
                    "hostPort": 9000,
                    "protocol": "tcp"
                }
            ],
            "essential": true,
            "entryPoint": [],
            "command": [],
            "environment": [
                {
                    "name": "SONARQUBE_JDBC_PASSWORD",
                    "value": "PASSWORD"
                },
                {
                    "name": "SONARQUBE_JDBC_URL",
                    "value": "LINK"
                },
                {
                    "name": "SONARQUBE_JDBC_USERNAME",
                    "value": "root"
                }
            ],
            "environmentFiles": [],
            "mountPoints": [
                {
                    "sourceVolume": "sonar-data",
                    "containerPath": "/opt/sonarqube/data"
                },
                {
                    "sourceVolume": "sonar-extensions",
                    "containerPath": "/opt/sonarqube/extensions"
                }
            ],
            "volumesFrom": [],
            "secrets": [],
            "privileged": true,
            "dnsServers": [],
            "dnsSearchDomains": [],
            "extraHosts": [],
            "dockerSecurityOptions": [],
            "dockerLabels": {},
            "ulimits": [
                {
                    "name": "nofile",
                    "softLimit": 65535,
                    "hardLimit": 65535
                }
            ],
            "logConfiguration": {
                "logDriver": "awslogs",
                "options": {
                    "awslogs-group": "sonar-config3",
                    "awslogs-region": "us-east-1",
                    "awslogs-stream-prefix": "ecs"
                },
                "secretOptions": []
            },
            "systemControls": []
        }
    ],
    "family": "sonar-task-def2",
    "taskRoleArn": "arn:aws:iam::ACCOUNT:role/sonar-config3-EcsTaskExecutionRole-1UXV6AQJSBHAN",
    "executionRoleArn": "arn:aws:iam::ACCOUNT:role/sonar-config3-EcsTaskExecutionRole-1UXV6AQJSBHAN",
    "networkMode": "awsvpc",
    "revision": 20,
    "volumes": [
        {
            "name": "sonar-data",
            "host": {
                "sourcePath": "/opt/sonarqube/data"
            }
        },
        {
            "name": "sonar-extensions",
            "host": {
                "sourcePath": "/opt/sonarqube/extensions"
            }
        }
    ],
    "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.privileged-container"
        },
        {
            "name": "com.amazonaws.ecs.capability.docker-remote-api.1.17"
        },
        {
            "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"
        }
    ],
    "placementConstraints": [],
    "compatibilities": [
        "EC2"
    ],
    "requiresCompatibilities": [
        "EC2"
    ],
    "cpu": "2048",
    "memory": "2048",
    "registeredAt": "2023-03-16T13:49:38.721Z",
    "registeredBy": "arn:aws:sts::ACCOUNT:assumed-role/altitude-products-engineer/",EMAIL
    "tags": []
}
luketk
asked a year ago113 views
No Answers

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions