diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml new file mode 100644 index 0000000..9974506 --- /dev/null +++ b/.github/workflows/docker-publish.yml @@ -0,0 +1,68 @@ +name: Build, Test, and Publish Docker Image + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + build: + runs-on: ubuntu-latest + + steps: + # Step 1: Checkout the repository + - name: Checkout repository + uses: actions/checkout@v3 + + # Step 2: Set up Docker Buildx + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + # Step 3: Set up Docker Compose + - name: Set up Docker Compose + run: sudo apt-get install docker-compose + + # Step 4: Build and start services using Docker Compose + - name: Build and Start Docker Compose + run: docker-compose up --build -d + + # Step 5: Wait for PostgreSQL to be ready + - name: Wait for PostgreSQL + run: | + until docker-compose exec -T postgres pg_isready -h postgres -U indexer -d indexer; do + echo "Waiting for PostgreSQL..."; + sleep 3; + done + + # Step 6: Check Lazy Indexer logs (optional for debugging) + - name: Check Lazy Indexer logs + run: docker-compose logs lazy-indexer + + # Step 7: Retry migration for Lazy Indexer + - name: Run migration + run: | + for i in {1..10}; do + docker-compose exec -T lazy-indexer yarn migrate && break || (echo "Retrying migration in 5 seconds..." && sleep 5); + done + + # Step 8: Log in to Docker Hub using secrets + - name: Log in to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + # Step 9: Push the Docker image to Docker Hub using the secret username + - name: Build and Push Docker image + uses: docker/build-push-action@v5 + with: + context: . + push: true + tags: ${{ secrets.DOCKER_USERNAME }}/lazy-indexer:latest-1 + + # Step 10: Verify the image exists on Docker Hub using the secret username + - name: Image exists on Docker Hub + run: docker pull ${{ secrets.DOCKER_USERNAME }}/lazy-indexer:latest-1 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..ead1a67 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +# Use Node.js version 20 with Alpine as the base image +FROM node:20-alpine + +# Set the working directory in the container +WORKDIR /app + +# Copy package.json and yarn.lock to the container +COPY package.json yarn.lock ./ + +# Install dependencies +RUN yarn install + +# Copy all source files to the container +COPY . . + + +# Expose the port (if required by the application) +EXPOSE 3005 + + +# Run the backfill and stream concurrently +CMD ["sh", "-c", "yarn backfill & yarn stream"] diff --git a/docker-compose.yml b/docker-compose.yml index 658f06b..4c97bae 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,7 +5,7 @@ services: image: 'postgres:16-alpine' restart: unless-stopped ports: - - '5432:5432' # Use a port unlikely to be in use so the example "Just Works" + - '5432:5432' environment: - POSTGRES_DB=indexer - POSTGRES_USER=indexer @@ -13,22 +13,14 @@ services: volumes: - postgres-data:/var/lib/postgresql/data healthcheck: - # Need to specify name/user to avoid `FATAL: role "root" does not exist` errors in logs - test: - [ - 'CMD-SHELL', - 'env', - 'pg_isready', - '--dbname', - '$$POSTGRES_DB', - '-U', - '$$POSTGRES_USER', - ] - interval: 10s - timeout: 10s - retries: 3 + test: ['CMD-SHELL', 'pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB'] + interval: 5s # Check every 5 seconds for readiness + timeout: 5s # Allow up to 5 seconds for a response + retries: 3 # Fail after 3 unsuccessful attempts + start_period: 10s # Start checks after 10 seconds networks: - indexer-network + redis: image: 'redis:7.2-alpine' restart: unless-stopped @@ -38,13 +30,34 @@ services: ports: - '6379:6379' healthcheck: - test: ['CMD-SHELL', 'redis-cli', 'ping'] - interval: 10s - timeout: 10s - retries: 3 - start_period: 5s + test: ['CMD-SHELL', 'redis-cli ping'] + interval: 5s # Check every 5 seconds + timeout: 5s # Allow up to 5 seconds for a response + retries: 3 # Fail after 3 unsuccessful attempts + start_period: 5s # Start health checks after 5 seconds + networks: + - indexer-network + + lazy-indexer: + build: . + restart: unless-stopped + depends_on: + postgres: + condition: service_healthy + redis: + condition: service_healthy + environment: + - DATABASE_URL=postgresql://indexer:password@postgres:5432/indexer + - REDIS_URL=redis://redis:6379 + - HUB_REST_URL=https://hub.pinata.cloud + - HUB_RPC=hub-grpc.pinata.cloud + - HUB_SSL=true + - WORKER_CONCURRENCY=5 + - LOG_LEVEL=debug networks: - indexer-network + command: > + /bin/sh -c "yarn backfill & yarn stream" volumes: postgres-data: