## ## Production server config (wip) ## You probably want to run: ## export COMPOSE_FILE="compose.yaml:compose.production.yaml" ## docker compose up -d ## services: web: profiles: ["ol-web0", "ol-web1", "ol-web2", "ol-web3"] image: "${OLIMAGE:-openlibrary/olbase:latest}" restart: unless-stopped hostname: "$HOSTNAME" environment: - GUNICORN_OPTS= --workers 28 --timeout 300 --max-requests 1500 - OL_CONFIG=/olsystem/etc/openlibrary.yml # Note this won't work with uv pip, because uv makes a network request - BEFORE_START=pip install -e /booklending_utils volumes: - ../booklending_utils:/booklending_utils - ../olsystem:/olsystem - ../olsystem/etc/ia.ini:/home/openlibrary/.config/ia.ini fast_web: profiles: ["ol-web0", "ol-web1", "ol-web2", "ol-web3"] image: "${OLIMAGE:-openlibrary/olbase:latest}" restart: unless-stopped hostname: "$HOSTNAME" environment: - GUNICORN_OPTS= --workers 4 --timeout 300 --max-requests 5000 --max-requests-jitter 500 - OL_CONFIG=/olsystem/etc/openlibrary.yml volumes: - ../booklending_utils:/booklending_utils - ../olsystem:/olsystem - ../olsystem/etc/ia.ini:/home/openlibrary/.config/ia.ini solr: # Disabled until next solr reindex due to solr version upgrade profiles: ["NEVER-ol-solr0"] ports: - 8983:8983 environment: # See compose.yaml for docs # Keep SOLR_OPTS in sync with other instances of solr in compose files - SOLR_OPTS= -Dsolr.autoSoftCommit.maxTime=60000 -Dsolr.autoCommit.maxTime=120000 -Dsolr.max.booleanClauses=30000 -Dsolr.environment=prod -Dol.replication.role.leader=true # More memory for production - SOLR_JAVA_MEM=-Xms10g -Xmx10g # This might overwrite the above? - SOLR_HEAP=8g restart: unless-stopped solr_replica: # Disabled until next solr reindex due to solr version upgrade profiles: ["NEVER-ol-solr2"] extends: file: compose.yaml service: solr ports: - 8983:8983 environment: # See compose.yaml for docs # Keep SOLR_OPTS in sync with other instances of solr in compose files - SOLR_OPTS= -Dsolr.autoSoftCommit.maxTime=60000 -Dsolr.autoCommit.maxTime=120000 -Dsolr.max.booleanClauses=30000 -Dsolr.environment=prod -Dol.replication.role.follower=true -Dol.replication.leader=ol-solr0.us.archive.org:8983 -Dsolr.security.allow.urls=http://ol-solr0.us.archive.org:8983 # More memory for production - SOLR_JAVA_MEM=-Xms10g -Xmx10g # This might overwrite the above? - SOLR_HEAP=8g restart: unless-stopped solr_haproxy: profiles: ["ol-home0"] image: haproxy:2.9.15 restart: unless-stopped networks: - webnet volumes: - ./conf/solr/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro ports: - 8984:8984 logging: options: max-size: "512m" max-file: "4" solr_restarter: # Disabled for now ; seemed to be making things worse, and seems no longer needed profiles: ["ol-never"] build: context: scripts/solr_restarter args: - APT_MIRROR=${APT_MIRROR:-} - DOCKER_KEY_URL=${DOCKER_KEY_URL:-} - DOCKER_REPOSITORY_URL=${DOCKER_REPOSITORY_URL:-} restart: unless-stopped environment: - TEST_URL=http://openlibrary.org/search.json?q=hello&mode=everything&limit=0 - CONTAINER_NAMES=openlibrary-solr-1 openlibrary-solr_haproxy-1 - SEND_SLACK_MESSAGE=false env_file: - ../olsystem/etc/solr_restarter.env volumes: # Forward the docker socket, since this needs to be able to # run docker commands - "/var/run/docker.sock:/var/run/docker.sock" logging: options: max-size: "512m" max-file: "4" covers: profiles: ["ol-covers0"] image: "${OLIMAGE:-openlibrary/olbase:latest}" restart: unless-stopped hostname: "$HOSTNAME" environment: - GUNICORN_OPTS= --workers 30 --max-requests 500 - COVERSTORE_CONFIG=/olsystem/etc/coverstore.yml volumes: - ../olsystem:/olsystem - /1:/1 deploy: # Note: the replicas here must be kept in sync with the `upstream covers_backend` # value in `docker/covers_nginx.conf`. replicas: 2 covers_nginx: profiles: ["ol-covers0"] image: "${OLIMAGE:-openlibrary/olbase:latest}" user: root command: docker/ol-nginx-start.sh environment: - CRONTAB_FILES=/etc/cron.d/archive-webserver-logs /etc/cron.d/certbot - NGINX_DOMAIN=covers.openlibrary.org restart: unless-stopped hostname: "$HOSTNAME" depends_on: - covers volumes: - ./docker/nginx.conf:/etc/nginx/nginx.conf:ro - ./docker/covers_nginx.conf:/etc/nginx/sites-enabled/covers_nginx.conf:ro # letsencrypt - letsencrypt-data:/etc/letsencrypt - ../olsystem/etc/cron.d/certbot:/etc/cron.d/certbot # Needs access to openlibrary for static files - ../olsystem:/olsystem - /1/var/lib/openlibrary/sitemaps:/sitemaps # web log rotation - ../olsystem/etc/logrotate.d/nginx:/etc/logrotate.d/nginx # Persist the nginx logs - /1/var/log/nginx:/var/log/nginx # Archive nginx logs regularly - ../olsystem/etc/cron.d/archive-webserver-logs:/etc/cron.d/archive-webserver-logs - archive-webserver-logs-data:/archive-webserver-logs-data ports: - 80:80 - 443:443 networks: - webnet logging: options: max-size: "512m" max-file: "4" memcached: # The memcached cluster is currently managed manually on production profiles: ["ol-never"] cron-jobs: profiles: ["ol-home0"] image: "${OLIMAGE:-openlibrary/olbase:latest}" hostname: "$HOSTNAME" user: root command: docker/ol-cron-start.sh restart: unless-stopped volumes: - ../olsystem/etc/cron.d/openlibrary.ol_home0:/etc/cron.d/openlibrary.ol_home0:ro - ../olsystem:/olsystem - /1/var/tmp:/1/var/tmp networks: - webnet - dbnet infobase: profiles: ["ol-home0"] image: "${OLIMAGE:-openlibrary/olbase:latest}" restart: unless-stopped hostname: "$HOSTNAME" environment: - INFOBASE_OPTS=fastcgi - INFOBASE_CONFIG=/olsystem/etc/infobase.yml volumes: - ../olsystem:/olsystem - /1/var/lib/openlibrary/infobase:/var/lib/openlibrary/infobase web_haproxy: profiles: ["ol-www0"] image: haproxy:2.9.15 restart: unless-stopped hostname: "$HOSTNAME" networks: - webnet volumes: - ../olsystem/etc/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro expose: - 7072 ports: # For prometheus logging - 8405:8405 logging: options: max-size: "512m" max-file: "4" web_nginx: profiles: ["ol-www0"] restart: unless-stopped hostname: "ol-www0" # always want this hostname (or nginx backups will be misnamed) image: "${OLIMAGE:-openlibrary/olbase:latest}" user: root command: docker/ol-nginx-start.sh environment: - CRONTAB_FILES=/etc/cron.d/archive-webserver-logs /etc/cron.d/pull-sitemaps-from-ol-home0 /etc/cron.d/certbot - NGINX_DOMAIN=openlibrary.org www.openlibrary.org volumes: # letsencrypt - letsencrypt-data:/etc/letsencrypt - ../olsystem/etc/cron.d/certbot:/etc/cron.d/certbot # nginx configurations - ./docker/nginx.conf:/etc/nginx/nginx.conf:ro - ./docker/web_nginx.conf:/etc/nginx/sites-enabled/openlibrary.conf:ro # archive web log uploads - ../olsystem:/olsystem # web log rotation - ../olsystem/etc/logrotate.d/nginx:/etc/logrotate.d/nginx # Persist the nginx logs - /1/var/log/nginx:/var/log/nginx # sitemap generation (we also need olsystem/etc/cron.d + openlibrary/scripts) - /1/var/lib/openlibrary/sitemaps:/sitemaps # Archive nginx logs regularly - ../olsystem/etc/cron.d/archive-webserver-logs:/etc/cron.d/archive-webserver-logs - archive-webserver-logs-data:/archive-webserver-logs-data # Sitemaps - ../olsystem/etc/cron.d/pull-sitemaps-from-ol-home0:/etc/cron.d/pull-sitemaps-from-ol-home0 ports: - 80:80 - 443:443 networks: - webnet logging: options: max-size: "512m" max-file: "4" infobase_nginx: profiles: ["ol-home0"] image: "${OLIMAGE:-openlibrary/olbase:latest}" user: root command: docker/ol-nginx-start.sh restart: unless-stopped depends_on: - infobase volumes: - ./docker/nginx.conf:/etc/nginx/nginx.conf:ro - ./docker/infobase_nginx.conf:/etc/nginx/sites-enabled/infobase_nginx.conf:ro # Needs olsystem for black-listed IPs - ../olsystem:/olsystem # Log rotation - ../olsystem/etc/logrotate.d/nginx:/etc/logrotate.d/nginx ports: - 7000:7000 networks: - webnet affiliate-server: profiles: ["ol-home0"] image: "${OLIMAGE:-openlibrary/olbase:latest}" restart: unless-stopped hostname: "$HOSTNAME" environment: - AFFILIATE_CONFIG=/openlibrary.yml command: docker/ol-affiliate-server-start.sh ports: - 31337:31337 volumes: - ../olsystem:/olsystem - /opt/olsystem/etc/openlibrary.yml:/openlibrary.yml - /opt/olsystem/etc/infobase.yml:/infobase.yml networks: - webnet logging: options: max-size: "512m" max-file: "4" solr-updater: profiles: ["ol-home0"] image: "${OLIMAGE:-openlibrary/olbase:latest}" restart: unless-stopped hostname: "$HOSTNAME" environment: - OL_CONFIG=/olsystem/etc/openlibrary.yml - OL_URL=https://openlibrary.org/ - OL_SOLR_BASE_URL=http://ol-solr0:8983/solr/openlibrary - OL_SOLR_NEXT=false volumes: - ../olsystem:/olsystem # See https://github.com/internetarchive/olsystem/wiki/Solr-Re%E2%80%90Indexing - /www0_1:/1 logging: options: max-size: "512m" max-file: "4" # solr-updater running for the "next" version of solr we will deploy solr-next-updater: # Set it to something so that it never starts by default ; we have to # explicitly start it (usually only when a solr reindex project is in progress) profiles: ["ol-never"] image: "${OLIMAGE:-openlibrary/olbase:latest}" restart: unless-stopped hostname: "$HOSTNAME" init: true environment: - OL_CONFIG=/olsystem/etc/openlibrary.yml - OL_URL=https://openlibrary.org/ - OL_SOLR_BASE_URL=http://ol-solr1:8983/solr/openlibrary - OL_SOLR_NEXT=true - STATE_FILE=solr-next-update.offset - TRENDING_OFFSET_FILE=trending-next-update.offset - OL_SENTRY_ENVIRONMENT=testing volumes: - solr-updater-data:/solr-updater-data - ../olsystem:/olsystem # See https://github.com/internetarchive/olsystem/wiki/Solr-Re%E2%80%90Indexing - /www0_1:/1 command: docker/ol-solr-updater-start.sh networks: - webnet - dbnet importbot: profiles: ["ol-home0"] image: "${OLIMAGE:-openlibrary/olbase:latest}" command: docker/ol-importbot-start.sh restart: unless-stopped hostname: "$HOSTNAME" environment: - OL_CONFIG=/olsystem/etc/openlibrary.yml - OPENLIBRARY_RCFILE=/olsystem/etc/olrc-importbot volumes: - ../olsystem:/olsystem networks: - webnet - dbnet # This job runs various monitoring/grafana checks across the entire cluster. # It has access to the other nodes via the docker socket. monitoring: profiles: ["ol-web0", "ol-web1", "ol-web2", "ol-web3", "ol-covers0", "ol-www0", "ol-solr0", "ol-solr1", "ol-solr2", "ol-home0"] build: context: . dockerfile: scripts/monitoring/Dockerfile args: - APT_MIRROR=${APT_MIRROR:-} - DOCKER_KEY_URL=${DOCKER_KEY_URL:-} - DOCKER_REPOSITORY_URL=${DOCKER_REPOSITORY_URL:-} - PIP_INDEX_URL=${PIP_INDEX_URL:-} hostname: "$HOSTNAME" command: docker/ol-monitoring-start.sh restart: unless-stopped # Needed to access other containers' networks network_mode: host # Needed for py-spy cap_add: [SYS_PTRACE] # Needed for ps aux access across containers (py-spy) pid: host volumes: # Needed to inspect other docker containers - /var/run/docker.sock:/var/run/docker.sock # Needed to inspect fail2ban since it runs on the host - /var/run/fail2ban:/var/run/fail2ban logging: options: max-size: "512m" max-file: "4" volumes: archive-webserver-logs-data: letsencrypt-data: