# Runs the site from the published images. # # This file is what runs on the server. It pulls finished images and starts # them; it never builds anything, because the machine that runs this has less # memory than a Next.js build needs. # # The images are built by .github/workflows/build-images.yml on every push to # master and published to GitHub Container Registry. A deploy is: # # docker compose pull && docker compose up -d # # `docker compose -f docker-compose.build.yml up` builds from local source # instead, for working on the images themselves. name: sachviet services: api: # Replaced at deploy time by the tag the workflow published. The default # is `latest`, which is the moving tag for the newest build on master. image: ${API_IMAGE:-ghcr.io/nhannht/webdichvuvesinhcongnghiep-api:latest} restart: unless-stopped environment: API_HOST: 0.0.0.0 API_PORT: "8080" ADMIN_USERNAME: ${ADMIN_USERNAME} ADMIN_PASSWORD: ${ADMIN_PASSWORD} # The web container's service name. Resolvable on the compose network # and nowhere else. REVALIDATE_URL: http://web:3000/api/revalidate REVALIDATE_SECRET: ${REVALIDATE_SECRET} PUBLIC_ORIGIN: ${PUBLIC_ORIGIN} COOKIE_SECURE: ${COOKIE_SECURE} COOKIE_SAMESITE: ${COOKIE_SAMESITE:-lax} ALLOWED_ORIGINS: ${ALLOWED_ORIGINS:-} API_PUBLIC_ORIGIN: ${API_PUBLIC_ORIGIN:-} volumes: # The one thing a deploy must not replace. The database and every # uploaded photograph live in ./data on the host, so rebuilding or # replacing a container leaves the customer's content untouched. - ./data:/app/data ports: # Bound to loopback, so only something running on this machine can # connect. The tunnel is what reaches it, and the public path to it is # /api/v1 through Cloudflare. # # It is published rather than left on the compose network alone for one # reason: the web image is built in CI against the deployed API, and the # build fetches through the public hostname. That path has to reach the # API without the web container existing, because the web container is # what is being built. # # Publishing it as 0.0.0.0:8080 instead would put an unauthenticated API # on the instance's public address. Do not. - "127.0.0.1:8080:8080" networks: - internal web: image: ${WEB_IMAGE:-ghcr.io/nhannht/webdichvuvesinhcongnghiep-web:latest} restart: unless-stopped environment: API_INTERNAL_URL: http://api:8080 PUBLIC_ORIGIN: ${PUBLIC_ORIGIN} REVALIDATE_SECRET: ${REVALIDATE_SECRET} WEB_HOST: 0.0.0.0 WEB_PORT: "3000" ports: # Published so the tunnel can reach it. Bound to loopback, so nothing on # the public interface can connect: the only way in is the tunnel process # on this same machine. # # This matters. Publishing it as 0.0.0.0:3000 would put an # unauthenticated site on the instance's public address, and the # security group would be the only thing left guarding it. - "127.0.0.1:3000:3000" depends_on: api: condition: service_healthy networks: - internal networks: internal: driver: bridge