diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 72269ac2..a4a65db4 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -4,6 +4,9 @@ on: push: branches: - development + paths-ignore: + - '**.md' + - '.gitignore' workflow_dispatch: inputs: tag_name: @@ -16,7 +19,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 + with: + fetch-depth: 1 - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -34,7 +39,10 @@ jobs: - name: Cache npm dependencies uses: actions/cache@v3 with: - path: ~/.npm + path: | + ~/.npm + node_modules + */*/node_modules key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} restore-keys: | ${{ runner.os }}-node- @@ -79,6 +87,7 @@ jobs: cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max build-args: | BUILDKIT_INLINE_CACHE=1 + BUILDKIT_CONTEXT_KEEP_GIT_DIR=1 outputs: type=registry,compression=zstd,compression-level=19 - name: Move cache @@ -87,11 +96,13 @@ jobs: mv /tmp/.buildx-cache-new /tmp/.buildx-cache - name: Notify via ntfy + if: success() run: | curl -d "Docker image build and push completed successfully for tag: ${{ env.IMAGE_TAG }}" \ https://ntfy.karmaa.site/termix-build - name: Delete all untagged image versions + if: success() uses: quartx-analytics/ghcr-cleaner@v1 with: owner-type: user @@ -100,6 +111,7 @@ jobs: delete-untagged: true - name: Cleanup Docker Images Locally + if: always() run: | docker image prune -af docker system prune -af --volumes \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile index 180ba179..7b7916af 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -2,7 +2,8 @@ FROM node:18-alpine AS frontend-builder WORKDIR /app COPY package*.json ./ -RUN npm ci +RUN --mount=type=cache,target=/root/.npm \ + npm ci COPY . . RUN npm run build @@ -10,53 +11,62 @@ RUN npm run build FROM node:18-alpine AS backend-builder WORKDIR /app COPY package*.json ./ -RUN npm ci --only=production +RUN --mount=type=cache,target=/root/.npm \ + npm ci --only=production COPY src/backend/ ./src/backend/ -# Stage 3: Build bcrypt for the target platform +# Stage 3: Build bcrypt for Ubuntu FROM ubuntu:focal AS bcrypt-builder ENV DEBIAN_FRONTEND=noninteractive \ NODE_VERSION=18.x WORKDIR /app COPY package*.json ./ -RUN apt-get update && \ +RUN --mount=type=cache,target=/var/cache/apt \ + --mount=type=cache,target=/var/lib/apt \ + apt-get update && \ apt-get install -y --no-install-recommends \ python3 make g++ wget ca-certificates gnupg && \ wget -qO- https://deb.nodesource.com/setup_${NODE_VERSION} | bash - && \ apt-get update && \ apt-get install -y nodejs && \ - npm ci --only=production bcrypt && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* /var/cache/apt/* /root/.npm /tmp/* + npm ci --only=production bcrypt # Final stage FROM ubuntu:focal ENV DEBIAN_FRONTEND=noninteractive \ NODE_VERSION=18.x \ MONGO_VERSION=4.4.24 \ + MONGO_URL=mongodb://localhost:27017/termix \ + MONGODB_DATA_DIR=/data/db \ + MONGODB_LOG_DIR=/var/log/mongodb \ PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" -# Create users +# Create users first RUN groupadd -r mongodb && useradd -r -g mongodb mongodb \ && groupadd -r node && useradd -r -g node -m node -# Install dependencies -RUN set -ex \ - && apt-get update \ - && apt-get install -y --no-install-recommends \ - ca-certificates gnupg wget nginx-light \ - && wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | apt-key add - \ - && echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/4.4 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.4.list \ - && wget -qO- https://deb.nodesource.com/setup_${NODE_VERSION} | bash - \ - && apt-get update \ - && apt-get install -y --no-install-recommends \ +# Install all dependencies in one layer +RUN --mount=type=cache,target=/var/cache/apt \ + --mount=type=cache,target=/var/lib/apt \ + set -ex && \ + apt-get update && \ + apt-get install -y --no-install-recommends \ + ca-certificates \ + gnupg \ + nginx-light \ + wget && \ + wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | apt-key add - && \ + echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/4.4 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.4.list && \ + wget -qO- https://deb.nodesource.com/setup_${NODE_VERSION} | bash - && \ + apt-get update && \ + apt-get install -y --no-install-recommends \ nodejs \ mongodb-org-server=${MONGO_VERSION} \ - mongodb-org-shell=${MONGO_VERSION} \ - && apt-get clean \ - && rm -rf /var/lib/apt/lists/* /var/cache/apt/* /root/.npm /tmp/* \ - && mkdir -p /data/db /var/log/mongodb /var/run/mongodb \ - && chown -R mongodb:mongodb /data/db /var/log/mongodb /var/run/mongodb + mongodb-org-shell=${MONGO_VERSION} && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* /var/cache/apt/* /root/.npm /tmp/* && \ + mkdir -p /data/db /var/log/mongodb /var/run/mongodb && \ + chown -R mongodb:mongodb /data/db /var/log/mongodb /var/run/mongodb # Setup nginx and frontend COPY docker/nginx.conf /etc/nginx/nginx.conf @@ -66,8 +76,9 @@ RUN chown -R www-data:www-data /usr/share/nginx/html # Setup backend WORKDIR /app COPY package*.json ./ -RUN npm ci --only=production --ignore-scripts \ - && rm -rf /root/.npm /tmp/* +RUN --mount=type=cache,target=/root/.npm \ + npm ci --only=production --ignore-scripts && \ + rm -rf /root/.npm /tmp/* COPY --from=bcrypt-builder /app/node_modules/bcrypt /app/node_modules/bcrypt COPY --from=backend-builder /app/src/backend ./src/backend RUN chown -R node:node /app diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 221b2d33..1a5b2c92 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -1,23 +1,23 @@ #!/bin/bash set -e -# Create required directories and set permissions +# Create required directories mkdir -p /data/db /var/log/mongodb /var/run/mongodb chown -R mongodb:mongodb /data/db /var/log/mongodb /var/run/mongodb -chown -R node:node /app +chmod 755 /data/db # Start MongoDB echo "Starting MongoDB..." -mongod --dbpath /data/db --logpath /var/log/mongodb/mongodb.log --bind_ip 0.0.0.0 & +gosu mongodb mongod --dbpath $MONGODB_DATA_DIR --logpath $MONGODB_LOG_DIR/mongodb.log --bind_ip 0.0.0.0 & MONGO_PID=$! # Wait for MongoDB to be ready echo "Waiting for MongoDB to start..." -until mongo --eval "print(\"waited for connection\")" > /dev/null 2>&1; do +until gosu mongodb mongo --eval "print(\"waited for connection\")" > /dev/null 2>&1; do sleep 0.5 if ! kill -0 $MONGO_PID 2>/dev/null; then echo "MongoDB failed to start. Checking logs:" - cat /var/log/mongodb/mongodb.log + cat $MONGODB_LOG_DIR/mongodb.log exit 1 fi done @@ -31,7 +31,6 @@ nginx echo "Starting backend services..." cd /app export NODE_ENV=production -export MONGO_URL=mongodb://localhost:27017/termix # Start SSH service su -s /bin/bash node -c "node src/backend/ssh.cjs" & @@ -42,4 +41,4 @@ su -s /bin/bash node -c "node src/backend/database.cjs" & echo "All services started" # Keep container running and show logs -tail -f /var/log/mongodb/mongodb.log \ No newline at end of file +tail -f $MONGODB_LOG_DIR/mongodb.log \ No newline at end of file diff --git a/docker/supervisord.conf b/docker/supervisord.conf deleted file mode 100644 index 1f9c2e1f..00000000 --- a/docker/supervisord.conf +++ /dev/null @@ -1,54 +0,0 @@ -[supervisord] -nodaemon=true -user=root -logfile=/var/log/supervisor/supervisord.log -pidfile=/var/run/supervisord.pid - -[program:mongodb] -command=/usr/bin/mongod --dbpath /data/db --logpath /var/log/mongodb/mongodb.log --bind_ip 0.0.0.0 -user=mongodb -autostart=true -autorestart=true -startsecs=10 -startretries=3 -stdout_logfile=/var/log/supervisor/mongodb.stdout.log -stderr_logfile=/var/log/supervisor/mongodb.stderr.log -priority=1 - -[program:nginx] -command=/usr/sbin/nginx -g "daemon off;" -user=root -autostart=true -autorestart=true -startsecs=5 -startretries=3 -stdout_logfile=/var/log/supervisor/nginx.stdout.log -stderr_logfile=/var/log/supervisor/nginx.stderr.log -priority=100 - -[program:ssh-service] -command=/usr/bin/node /app/src/backend/ssh.cjs -user=node -directory=/app -environment=NODE_ENV="production",PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" -autostart=true -autorestart=true -startsecs=10 -startretries=3 -stdout_logfile=/var/log/supervisor/ssh.stdout.log -stderr_logfile=/var/log/supervisor/ssh.stderr.log -priority=200 - -[program:database-service] -command=/usr/bin/node /app/src/backend/database.cjs -user=node -directory=/app -environment=NODE_ENV="production",MONGO_URL="mongodb://localhost:27017/termix",PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" -autostart=true -autorestart=true -startsecs=10 -startretries=3 -stdout_logfile=/var/log/supervisor/database.stdout.log -stderr_logfile=/var/log/supervisor/database.stderr.log -depends_on=mongodb -priority=300 \ No newline at end of file