Search code examples
network-programmingdocker-composerpcbitcoin

Running Docker Container in Host Mode Causes Networking Problems For Dependent Containers


I'm trying to install this service to run a visualizer on bitcoin's blockchain. The application itself isn't so important; the key point is that I'm trying to point it to my bitcoin RPC service that's running on the local host, not in another docker container. As such, I need to run the "api" service in host networking mode.

The problem is, when I do that, it seems to break nginx somewhere in the application stack. The following error is from the logs in my "web" container (docker-compose.yml is below for reference)

2023/03/03 22:22:54 [emerg] 1#1: host not found in upstream "api:6000" in /etc/nginx/conf.d/default.conf:42
nginx: [emerg] host not found in upstream "api:6000" in /etc/nginx/conf.d/default.conf:42

For the life of me I can't figure it out. When I take the "api" service off of host networking mode, suddenly the error above stops being thrown by my "web" container. But if I do that, the "api" container obviously is not able to connect to the bitcoin RPC service on localhost.

Any pointers on how to make this work would be very much appreciated!

My docker-compose file is:

version: "3"

services:
  web:
    image: ghcr.io/bitfeed-project/bitfeed-client:v2.3.4
    restart: on-failure
    stop_grace_period: 1m
    depends_on:
      - api
    environment:
      TARGET: docker
      BACKEND_HOST: api
      BACKEND_PORT: "6000" #modified because port 5000 is already in use by another service
    ports:
      - "3080:80" #modified because port 3000 is already in use by another service

  api:
    image: ghcr.io/bitfeed-project/bitfeed-server:v2.3.4
    user: "1000:1000"
    restart: on-failure
    stop_grace_period: 1m
    network_mode: host #added network_mode: host so that I can access bitcoin RPC on local machine
    environment:
      PORT: "6000" #modified because port 5000 is already in use by another service
      BITCOIN_HOST: "127.0.0.1" #modified to point to localhost
      BITCOIN_ZMQ_RAWBLOCK_PORT: 28332
      BITCOIN_ZMQ_RAWTX_PORT: 28333
      BITCOIN_ZMQ_SEQUENCE_PORT: 28334
      BITCOIN_RPC_PORT: 8332
      BITCOIN_RPC_USER: raspibolt
      BITCOIN_RPC_PASS: [password]

Tried:

  1. Changing ports (no effect)
  2. Running "api" service in bridge mode (can't connect to bitcoin RPC service on localhost this way)
  3. Attempting to modify /etc/nginx/conf.d/default.conf in the "web" service container (confusingly, the expected value of "api:6000" already appears to be there)

Expected result: the API connects to the bitcoin RPC back end and synchronizes mempool; the web service then connects to the API on port 5000 and the web app becomes accessible at localhost:3080

Actual result: the API connects to the bitcoin RPC back end and synchronizes mempool; the web service keeps dying because "api:6000" is expected as an upstream value in /etc/nginx/conf.d/default.conf but is not found.


Solution

  • You need to:

    1. Specify network_mode: host for both web and api services. Note that port mapping is incompatible with network mode host. It means that web service will try to use your 127.0.0.1:80. Make sure port 80 is available or make web use some other port;
    2. Make the web service look for the API at 127.0.0.1:6000 instead of api:6000. You should be able to achieve this by modifying the web's BACKEND_HOST env variable in docker-compose.yml if I understand correctly.

    Explanation: for all 3 pieces to communicate well they should be on the same network. You have 2 options: host or docker bridge. If you don't want to dockerize your RPC bitcoin service and make it a part of docker-compose you are left with the option to deploy web and api services in the host network. When you do it, api is no longer available at api:6000 because it's the bridge network address. Instead, it becomes available at the host network, hence 127.0.0.1:6000.