version: "3" services: db: container_name: db build: ./docker/db restart: unless-stopped healthcheck: test: ["CMD-SHELL", "PGPASSWORD=${POSTGRES_PASSWORD} psql -U ${POSTGRES_USER} ${POSTGRES_DB} -c 'SELECT 1 FROM users LIMIT 1'"] interval: 10s timeout: 10s retries: 10 start_period: 1m expose: - "5432" ports: - "5431:5432" env_file: - .env.sndev volumes: - ./docker/db/seed.sql:/docker-entrypoint-initdb.d/seed.sql - db:/var/lib/postgresql/data app: container_name: app build: context: ./ args: - UID=${CURRENT_UID} - GID=${CURRENT_GID} restart: unless-stopped healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000"] interval: 10s timeout: 10s retries: 10 start_period: 1m depends_on: db: condition: service_healthy restart: true opensearch: condition: service_healthy restart: true sn_lnd: condition: service_healthy restart: true env_file: - .env.sndev expose: - "3000" ports: - "3000:3000" volumes: - ./:/app links: - db - opensearch - sn_lnd worker: container_name: worker build: context: ./worker args: - UID=${CURRENT_UID} - GID=${CURRENT_GID} restart: unless-stopped depends_on: db: condition: service_healthy restart: true app: condition: service_healthy restart: true opensearch: condition: service_healthy restart: true sn_lnd: condition: service_healthy restart: true env_file: - .env.sndev volumes: - ./:/app links: - db - app - opensearch - sn_lnd entrypoint: ["/bin/sh", "-c"] command: - npm run worker:dev imgproxy: container_name: imgproxy image: darthsim/imgproxy:v3.18.1 healthcheck: test: [ "CMD", "imgproxy", "health" ] interval: 10s timeout: 10s retries: 10 start_period: 1m restart: unless-stopped env_file: - .env.sndev ports: - "3001:8080" links: - app opensearch: image: opensearchproject/opensearch:latest container_name: opensearch healthcheck: test: ["CMD-SHELL", "curl -ku admin:${OPENSEARCH_INITIAL_ADMIN_PASSWORD} --silent --fail localhost:9200/_cluster/health || exit 1"] interval: 10s timeout: 10s retries: 10 start_period: 1m restart: unless-stopped env_file: - .env.sndev environment: - OPENSEARCH_INITIAL_ADMIN_PASSWORD=mVchg1T5oA9wudUh ports: - 9200:9200 # REST API - 9600:9600 # Performance Analyzer volumes: - os:/usr/share/opensearch/data command: > bash -c ' set -m /usr/share/opensearch/opensearch-docker-entrypoint.sh & until curl -sS "http://localhost:9200/_cat/health?h=status" -ku admin:${OPENSEARCH_INITIAL_ADMIN_PASSWORD} | grep -q "green\|yellow"; do echo "Waiting for OpenSearch to start..." sleep 1 done echo "OpenSearch started." curl -X PUT "http://localhost:9200/item" -ku admin:${OPENSEARCH_INITIAL_ADMIN_PASSWORD} echo "OpenSearch index created." fg ' os-dashboard: image: opensearchproject/opensearch-dashboards:latest container_name: os-dashboard restart: unless-stopped depends_on: opensearch: condition: service_healthy restart: true env_file: - .env.sndev environment: - opensearch.ssl.verificationMode=none - OPENSEARCH_HOSTS=http://opensearch:9200 - server.ssl.enabled=false ports: - 5601:5601 expose: - "5601" links: - opensearch bitcoin: image: polarlightning/bitcoind:26.0 container_name: bitcoin restart: unless-stopped healthcheck: test: ["CMD-SHELL", "bitcoin-cli -chain=regtest -rpcport=${RPC_PORT} -rpcuser=${RPC_USER} -rpcpassword=${RPC_PASS} getblockchaininfo"] interval: 10s timeout: 10s retries: 10 start_period: 1m command: - 'bitcoind' - '-server=1' - '-regtest=1' - '-rpcauth=${RPC_USER}:${RPC_AUTH}' - '-debug=1' - '-zmqpubrawblock=tcp://0.0.0.0:${ZMQ_BLOCK_PORT}' - '-zmqpubrawtx=tcp://0.0.0.0:${ZMQ_TX_PORT}' - '-txindex=1' - '-dnsseed=0' - '-upnp=0' - '-rpcbind=0.0.0.0' - '-rpcallowip=0.0.0.0/0' - '-rpcport=${RPC_PORT}' - '-rest' - '-listen=1' - '-listenonion=0' - '-fallbackfee=0.0002' - '-blockfilterindex=1' - '-peerblockfilters=1' expose: - "${RPC_PORT}" - "${P2P_PORT}" - "${ZMQ_BLOCK_PORT}" - "${ZMQ_TX_PORT}" volumes: - bitcoin:/home/bitcoin/.bitcoin labels: ofelia.enabled: "true" ofelia.job-exec.minecron.schedule: "@every 1m" ofelia.job-exec.minecron.command: > bash -c ' blockcount=$$(bitcoin-cli -chain=regtest -rpcport=${RPC_PORT} -rpcuser=${RPC_USER} -rpcpassword=${RPC_PASS} getblockcount 2>/dev/null) if (( blockcount <= 0 )); then echo "Mining 10 blocks to sn_lnd and stacker_lnd..." bitcoin-cli -chain=regtest -rpcport=${RPC_PORT} -rpcuser=${RPC_USER} -rpcpassword=${RPC_PASS} generatetoaddress 100 ${LND_ADDR} bitcoin-cli -chain=regtest -rpcport=${RPC_PORT} -rpcuser=${RPC_USER} -rpcpassword=${RPC_PASS} generatetoaddress 100 ${STACKER_LND_ADDR} else echo "Mining a block to sn_lnd... ${LND_ADDR}" bitcoin-cli -chain=regtest -rpcport=${RPC_PORT} -rpcuser=${RPC_USER} -rpcpassword=${RPC_PASS} generatetoaddress 1 ${LND_ADDR} echo "Mining a block to stacker_lnd... ${STACKER_LND_ADDR}" bitcoin-cli -chain=regtest -rpcport=${RPC_PORT} -rpcuser=${RPC_USER} -rpcpassword=${RPC_PASS} generatetoaddress 1 ${STACKER_LND_ADDR} fi ' sn_lnd: build: context: ./docker/lnd args: - LN_NODE_FOR=sn container_name: sn_lnd restart: unless-stopped healthcheck: test: ["CMD-SHELL", "lncli", "getinfo"] interval: 10s timeout: 10s retries: 10 start_period: 1m depends_on: bitcoin: condition: service_healthy restart: true env_file: - .env.sndev command: - 'lnd' - '--noseedbackup' - '--trickledelay=5000' - '--alias=sn_lnd' - '--externalip=sn_lnd' - '--tlsextradomain=sn_lnd' - '--tlsextradomain=host.docker.internal' - '--listen=0.0.0.0:${LND_P2P_PORT}' - '--rpclisten=0.0.0.0:${LND_GRPC_PORT}' - '--restlisten=0.0.0.0:${LND_REST_PORT}' - '--bitcoin.active' - '--bitcoin.regtest' - '--bitcoin.node=bitcoind' - '--bitcoind.rpchost=bitcoin' - '--bitcoind.rpcuser=${RPC_USER}' - '--bitcoind.rpcpass=${RPC_PASS}' - '--bitcoind.zmqpubrawblock=tcp://bitcoin:${ZMQ_BLOCK_PORT}' - '--bitcoind.zmqpubrawtx=tcp://bitcoin:${ZMQ_TX_PORT}' - '--protocol.wumbo-channels' - '--maxchansize=1000000000' - '--allow-circular-route' - '--bitcoin.defaultchanconfs=0' - '--maxpendingchannels=10' expose: - "${LND_P2P_PORT}" ports: - "${LND_REST_PORT}:${LND_REST_PORT}" - "${LND_GRPC_PORT}:${LND_GRPC_PORT}" volumes: - sn_lnd:/home/lnd/.lnd labels: ofelia.enabled: "true" ofelia.job-exec.sn_channel_cron.schedule: "@every 1m" ofelia.job-exec.sn_channel_cron.command: > su lnd -c bash -c " if [ $$(lncli listchannels | jq '.member | length') -ge 1 ]; then exit 0 else lncli openchannel --node_key=$STACKER_LND_PUBKEY --connect stacker_lnd:9735 --sat_per_vbyte 1 --min_confs 0 --local_amt=1000000000 --push_amt=500000000 fi " stacker_lnd: build: context: ./docker/lnd args: - LN_NODE_FOR=stacker container_name: stacker_lnd restart: unless-stopped healthcheck: test: ["CMD-SHELL", "lncli", "getinfo"] interval: 10s timeout: 10s retries: 10 start_period: 1m depends_on: bitcoin: condition: service_healthy restart: true env_file: - .env.sndev command: - 'lnd' - '--noseedbackup' - '--trickledelay=5000' - '--alias=stacker_lnd' - '--externalip=stacker_lnd' - '--tlsextradomain=stacker_lnd' - '--tlsextradomain=host.docker.internal' - '--listen=0.0.0.0:${LND_P2P_PORT}' - '--rpclisten=0.0.0.0:${LND_GRPC_PORT}' - '--restlisten=0.0.0.0:${LND_REST_PORT}' - '--bitcoin.active' - '--bitcoin.regtest' - '--bitcoin.node=bitcoind' - '--bitcoind.rpchost=bitcoin' - '--bitcoind.rpcuser=${RPC_USER}' - '--bitcoind.rpcpass=${RPC_PASS}' - '--bitcoind.zmqpubrawblock=tcp://bitcoin:${ZMQ_BLOCK_PORT}' - '--bitcoind.zmqpubrawtx=tcp://bitcoin:${ZMQ_TX_PORT}' - '--protocol.wumbo-channels' - '--maxchansize=1000000000' - '--allow-circular-route' - '--bitcoin.defaultchanconfs=0' - '--maxpendingchannels=10' expose: - "${LND_P2P_PORT}" ports: - "${STACKER_LND_REST_PORT}:${LND_REST_PORT}" - "${STACKER_LND_GRPC_PORT}:${LND_GRPC_PORT}" volumes: - stacker_lnd:/home/lnd/.lnd labels: ofelia.enabled: "true" ofelia.job-exec.stacker_channel_cron.schedule: "@every 1m" ofelia.job-exec.stacker_channel_cron.command: > su lnd -c bash -c " if [ $$(lncli listchannels | jq '.member | length') -ge 1 ]; then exit 0 else lncli openchannel --node_key=$LND_PUBKEY --connect sn_lnd:9735 --sat_per_vbyte 1 --min_confs 0 --local_amt=1000000000 --push_amt=500000000 fi " channdler: image: mcuadros/ofelia:latest container_name: channdler depends_on: - bitcoin - sn_lnd - stacker_lnd restart: unless-stopped command: daemon --docker -f label=com.docker.compose.project=${COMPOSE_PROJECT_NAME} volumes: - /var/run/docker.sock:/var/run/docker.sock:ro volumes: db: os: bitcoin: sn_lnd: stacker_lnd: