diff --git a/Dockerfile b/Dockerfile index f4043557..1b40aa30 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,148 +1,136 @@ # OPA BUILD STAGE ----------------------------------- -# build opa from source or download precompiled binary +# Build OPA from source or download precompiled binary # --------------------------------------------------- FROM golang:bullseye AS opa_build COPY custom* /custom COPY factdb* /factdb +# Build OPA binary if custom_opa.tar.gz is provided RUN if [ -f /custom/custom_opa.tar.gz ]; \ then \ cd /custom && \ tar xzf custom_opa.tar.gz && \ go build -ldflags="-extldflags=-static" -o /opa && \ - rm -rf /custom ; \ + rm -rf /custom; \ else \ case $(uname -m) in \ - x86_64) \ - curl -L -o /opa https://openpolicyagent.org/downloads/latest/opa_linux_amd64_static ; \ - ;; \ - aarch64) \ - curl -L -o /opa https://openpolicyagent.org/downloads/latest/opa_linux_arm64_static ; \ - ;; \ - *) \ - echo "Unknown architecture." ; \ - exit 1 ; \ - ;; \ - esac ; \ + x86_64) curl -L -o /opa https://openpolicyagent.org/downloads/latest/opa_linux_amd64_static ;; \ + aarch64) curl -L -o /opa https://openpolicyagent.org/downloads/latest/opa_linux_arm64_static ;; \ + *) echo "Unknown architecture." && exit 1 ;; \ + esac; \ fi +# Build or copy factdb binary RUN if [ -f /factdb/factdb.tar.gz ]; \ then \ cd /factdb && \ tar xzf factdb.tar.gz && \ go build -ldflags="-extldflags=-static" -o /bin/factdb ./cmd/factstore_server && \ - rm -rf /factdb ; \ + rm -rf /factdb; \ else \ case $(uname -m) in \ x86_64) \ if [ -f /factdb/factstore_server-linux-amd64 ]; then \ cp /factdb/factstore_server-linux-amd64 /bin/factdb; \ else \ - echo "factstore_server-linux-amd64 not found." ; \ + echo "factstore_server-linux-amd64 not found."; \ if [ "$ALLOW_MISSING_FACTSTORE" = "false" ]; then \ - echo "Missing Factstore is not allowed, exiting..."; exit 1; \ + echo "Missing Factstore is not allowed, exiting..."; \ + exit 1; \ else \ echo "Missing Factstore is allowed, continuing..."; \ - touch /bin/factdb ; \ - fi \ + touch /bin/factdb; \ + fi; \ fi \ ;; \ aarch64) \ if [ -f /factdb/factstore_server-linux-arm64 ]; then \ cp /factdb/factstore_server-linux-arm64 /bin/factdb; \ else \ - echo "factstore_server-linux-arm64 not found." ; \ + echo "factstore_server-linux-arm64 not found."; \ if [ "$ALLOW_MISSING_FACTSTORE" = "false" ]; then \ - echo "Missing Factstore is not allowed, exiting..."; exit 1; \ + echo "Missing Factstore is not allowed, exiting..."; \ + exit 1; \ else \ echo "Missing Factstore is allowed, continuing..."; \ - touch /bin/factdb ; \ - fi \ + touch /bin/factdb; \ + fi; \ fi \ ;; \ *) \ - echo "Unknown architecture." ; \ - exit 1 ; \ + echo "Unknown architecture."; \ + exit 1; \ ;; \ - esac ; \ + esac; \ fi - # MAIN IMAGE ---------------------------------------- -# most of the time only this image should be built +# Main image setup (optimized) # --------------------------------------------------- FROM python:3.10-alpine WORKDIR /app -RUN addgroup -S permit -g 1001 -RUN adduser -S -s /bin/bash -u 1000 -G permit -h /home/permit permit +# Create necessary user and group in a single step +RUN addgroup -S permit -g 1001 && \ + adduser -S -s /bin/bash -u 1000 -G permit -h /home/permit permit -# create backup directory +# Create backup directory with permissions RUN mkdir -p /app/backup && chmod -R 777 /app/backup -# install linux libraries necessary to compile some python packages +# Install necessary libraries in a single RUN command RUN apk update && \ apk add --no-cache bash build-base libffi-dev libressl-dev musl-dev zlib-dev gcompat -# Copy custom opa binary -RUN mkdir /app/bin -RUN chown -R permit:permit /app/bin +# Copy OPA and factdb binaries from the build stage COPY --from=opa_build --chmod=755 /opa /app/bin/opa -ENV OPAL_INLINE_OPA_EXEC_PATH="/app/bin/opa" - COPY --from=opa_build --chmod=755 /bin/factdb /app/bin/factdb -ENV PDP_FACTDB_BINARY_PATH="/app/bin/factdb" -# bash is needed for ./start/sh script -COPY scripts ./ +# Environment variables for OPA and FactDB +ENV OPAL_INLINE_OPA_EXEC_PATH="/app/bin/opa" +ENV PDP_FACTDB_BINARY_PATH="/app/bin/factdb" -RUN mkdir -p /config -RUN chown -R permit:permit /config +# Copy required scripts +COPY scripts /scripts -# copy wait-for-it (use only for development! e.g: docker compose) -COPY scripts/wait-for-it.sh /usr/wait-for-it.sh -RUN chmod +x /usr/wait-for-it.sh +# Set permissions and ownership for the application +RUN mkdir -p /config && chown -R permit:permit /config +RUN chmod +x /scripts/wait-for-it.sh && \ + chmod +x /scripts/start.sh -# copy startup script -COPY ./scripts/start.sh ./start.sh -RUN chmod +x ./start.sh +# Ensure the `permit` user has the correct permissions for home directory and binaries +RUN chown -R permit:permit /home/permit /app /usr/local/bin /scripts -RUN chown -R permit:permit /home/permit -RUN chown -R permit:permit /usr/ +# Switch to permit user USER permit -# copy Kong route-to-resource translation table +# Copy Kong routes and Gunicorn config COPY kong_routes.json /config/kong_routes.json - -# copy gunicorn_config COPY ./scripts/gunicorn_conf.py ./gunicorn_conf.py -# install python dependencies +USER root + +# Install python dependencies in one command to optimize layer size COPY ./requirements.txt ./requirements.txt -RUN pip install -r requirements.txt -RUN python -m pip uninstall -y pip setuptools -RUN rm -r /usr/local/lib/python3.10/ensurepip +RUN pip install -r requirements.txt && \ + python -m pip uninstall -y pip setuptools && \ + rm -r /usr/local/lib/python3.10/ensurepip + +USER permit -# copy app code -COPY ./horizon ./horizon +# Copy the application code +COPY ./horizon /app/horizon -# copy version file +# Version file for the application COPY ./permit_pdp_version /app/permit_pdp_version -# Make sure scripts in .local are usable: -ENV PATH="/:/app/bin:/home/permit/.local/bin:$PATH" -# uvicorn config ------------------------------------ - -# WARNING: do not change the number of workers on the opal client! -# only one worker is currently supported for the client. +# Set the PATH to ensure the local binary paths are used +ENV PATH="/app/bin:/home/permit/.local/bin:$PATH" -# number of uvicorn workers +# Uvicorn configuration ENV UVICORN_NUM_WORKERS=1 -# uvicorn asgi app ENV UVICORN_ASGI_APP="horizon.main:app" -# uvicorn port ENV UVICORN_PORT=7000 # opal configuration -------------------------------- @@ -165,10 +153,9 @@ ENV PDP_FACTDB_BINARY_PATH="/app/bin/factdb" # This is a default PUBLIC (not secret) key, # and it is here as a safety measure on purpose. ENV OPAL_AUTH_PUBLIC_KEY="ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDe2iQ+/E01P2W5/EZwD5NpRiSQ8/r/k18pFnym+vWCSNMWpd9UVpgOUWfA9CAX4oEo5G6RfVVId/epPH/qVSL87uh5PakkLZ3E+PWVnYtbzuFPs/lHZ9HhSqNtOQ3WcPDTcY/ST2jyib2z0sURYDMInSc1jnYKqPQ6YuREdoaNdPHwaTFN1tEKhQ1GyyhL5EDK97qU1ejvcYjpGm+EeE2sjauHYn2iVXa2UA9fC+FAKUwKqNcwRTf3VBLQTE6EHGWbxVzXv1Feo8lPZgL7Yu/UPgp7ivCZhZCROGDdagAfK9sveYjkKiWCLNUSpado/E5Vb+/1EVdAYj6fCzk45AdQzA9vwZefP0sVg7EuZ8VQvlz7cU9m+XYIeWqduN4Qodu87rtBYtSEAsru/8YDCXBDWlLJfuZb0p/klbte3TayKnQNSWD+tNYSJHrtA/3ZewP+tGDmtgLeB38NLy1xEsgd31v6ISOSCTHNS8ku9yWQXttv0/xRnuITr8a3TCLuqtUrNOhCx+nKLmYF2cyjYeQjOWWpn/Z6VkZvOa35jhG1ETI8IwE+t5zXqrf2s505mh18LwA1DhC8L/wHk8ZG7bnUe56QwxEo32myUBN8nHdu7XmPCVP8MWQNLh406QRAysishWhXVs/+0PbgfBJ/FxKP8BXW9zqzeIG+7b/yk8tRHQ==" -# expose sidecar port -EXPOSE 7000 -# expose opa directly -EXPOSE 8181 +# 7000 sidecar port +# 8181 opa port +EXPOSE 7000 8181 -# run gunicorn -CMD ["/app/start.sh"] +# Run the application using the startup script +CMD ["/scripts/start.sh"]