diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..bc68941 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,60 @@ +# syntax=docker/dockerfile:1.7 + +ARG NODE_VERSION=22-bookworm-slim + +FROM node:${NODE_VERSION} AS package + +ARG PI_WEB_VERSION=latest +ARG PI_VERSION=latest +ARG CACHE_BUST=local + +ENV NPM_CONFIG_UPDATE_NOTIFIER=false + +RUN apt-get update \ + && apt-get install -y --no-install-recommends ca-certificates g++ make python3 \ + && rm -rf /var/lib/apt/lists/* + +RUN set -eux; \ + echo "PI WEB Docker build cache bust: ${CACHE_BUST}"; \ + npm install -g --omit=dev --no-audit --no-fund \ + "@jmfederico/pi-web@${PI_WEB_VERSION}" \ + "@earendil-works/pi-coding-agent@${PI_VERSION}"; \ + npm cache clean --force + +FROM node:${NODE_VERSION} AS runtime + +ENV NODE_ENV=production \ + NPM_CONFIG_UPDATE_NOTIFIER=false \ + HOME=/data/home \ + XDG_CONFIG_HOME=/data/config \ + PI_WEB_HOST=0.0.0.0 \ + PI_WEB_PORT=8504 \ + PI_WEB_DATA_DIR=/data/pi-web \ + PI_WEB_SESSIOND_SOCKET=/data/pi-web/sessiond.sock \ + PI_CODING_AGENT_DIR=/data/pi-agent \ + SHELL=/bin/bash \ + TERM=xterm-256color + +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + bash \ + ca-certificates \ + curl \ + git \ + openssh-client \ + procps \ + tini \ + && rm -rf /var/lib/apt/lists/* \ + && mkdir -p /data/home /data/config /data/pi-web /data/pi-agent /workspace \ + && chown -R node:node /data /workspace + +COPY --from=package /usr/local/lib/node_modules /usr/local/lib/node_modules +COPY --from=package /usr/local/bin /usr/local/bin + +WORKDIR /workspace +USER node + +EXPOSE 8504 + +ENTRYPOINT ["tini", "--"] +CMD ["pi-web-server"] diff --git a/docker/compose.yml b/docker/compose.yml new file mode 100644 index 0000000..7fd5975 --- /dev/null +++ b/docker/compose.yml @@ -0,0 +1,81 @@ +name: pi-web + +x-pi-web-build: &pi-web-build + context: . + dockerfile: Dockerfile + args: + PI_WEB_VERSION: ${PI_WEB_VERSION:-latest} + PI_VERSION: ${PI_VERSION:-latest} + CACHE_BUST: ${CACHE_BUST:-local} + +x-pi-web-environment: &pi-web-environment + HOME: /data/home + XDG_CONFIG_HOME: /data/config + PI_WEB_DATA_DIR: /data/pi-web + PI_WEB_SESSIOND_SOCKET: /data/pi-web/sessiond.sock + PI_CODING_AGENT_DIR: /data/pi-agent + PI_WEB_MAX_UPLOAD_BYTES: ${PI_WEB_MAX_UPLOAD_BYTES:-67108864} + +x-pi-web-volumes: &pi-web-volumes + - type: bind + source: ${PI_WEB_DOCKER_DATA_DIR:-./data} + target: /data + - type: bind + source: /var/run/docker.sock + target: /var/run/docker.sock + - type: bind + source: /srv + target: /srv + - type: bind + source: /opt + target: /opt + - type: bind + source: /home + target: /home + - type: bind + source: / + target: /host + read_only: true + +services: + sessiond: + build: *pi-web-build + image: ${PI_WEB_IMAGE:-pi-web:local} + command: ["pi-web-sessiond"] + restart: unless-stopped + user: "${PI_WEB_UID:-1000}:${PI_WEB_GID:-1000}" + group_add: + - "${DOCKER_GID:-0}" + environment: *pi-web-environment + volumes: *pi-web-volumes + healthcheck: + test: ["CMD-SHELL", "test -S /data/pi-web/sessiond.sock"] + interval: 10s + timeout: 3s + retries: 12 + start_period: 10s + + web: + build: *pi-web-build + image: ${PI_WEB_IMAGE:-pi-web:local} + command: ["pi-web-server"] + restart: unless-stopped + depends_on: + sessiond: + condition: service_healthy + user: "${PI_WEB_UID:-1000}:${PI_WEB_GID:-1000}" + group_add: + - "${DOCKER_GID:-0}" + environment: + <<: *pi-web-environment + PI_WEB_HOST: 0.0.0.0 + PI_WEB_PORT: "8504" + ports: + - "${PI_WEB_BIND_ADDR:-127.0.0.1}:${PI_WEB_PORT:-8504}:8504" + volumes: *pi-web-volumes + healthcheck: + test: ["CMD-SHELL", "curl -fsS http://127.0.0.1:8504/api/pi-web/runtime >/dev/null"] + interval: 10s + timeout: 5s + retries: 12 + start_period: 10s