dockerdocker-composeredismedusajs

Subscribers in Docker using Redis and MedusaJs


I have an issue setting up a subscriber in Medusa backend when running my application in Docker. I have created a docker-compose.yml which makes it possible to deploy and use both medusa_admin, my own storefront and the medusa_backend from docker. Also I have created my databases as docker containers (redis, postgres and a Solr for search optimization).

Below is my docker-compose.yml file:

version: "3.8"
services:
  backend:
    build:
      context: ./medusa_backend
      dockerfile: Dockerfile
    image: my_username/medusa_backend
    container_name: medusa_backend
    depends_on:
      - postgres
      - redis
    environment:
      DATABASE_URL: postgres://postgres:<my_password>@postgres:5432
      REDIS_URL: redis://redis:6379
      NODE_ENV: development
      JWT_SECRET: some_jwt_secret
      COOKIE_SECRET: some_cookie_secret
      PORT: 9000
      ADMIN_CORS: http://localhost:7000,http://localhost:7001,http://<my_server_ip>:7000,http://localhost:7000
      STORE_CORS: http://localhost:3000,http:///<my_server_ip>:8000,http://localhost:8000
    volumes:
      - ./medusa_backend/data:/var/lib/postgresql/data
    ports:
      - "9000:9000"
    networks:
      - alpha_solutions_docker_network
    restart: always

  postgres:
    image: postgres:10.4
    container_name: postgres
    ports:
      - "5432:5432"
    volumes:
      - ./postgres/data:/var/lib/postgresql/data
    networks:
      - alpha_solutions_docker_network
    restart: always
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=<my_password>
      - POSTGRES_DB=postgres
      - POSTGRES_INITDB_ARGS=--encoding=UTF-8

  redis:
    image: redis
    container_name: redis
    ports:
      - "6379:6379"
    networks:
      - alpha_solutions_docker_network
    restart: always

  admin:
    build:
      context: ./medusa_admin
      dockerfile: Dockerfile
    image: my_username/medusa_admin
    container_name: medusa_admin
    depends_on:
      - backend
    environment:
      HOST: 0.0.0.0
      PORT: 7000
    ports:
      - "7000:7000"
    networks:
      - alpha_solutions_docker_network
    restart: always

  storefront:
    build:
      context: ./nextjs_frontend
      dockerfile: Dockerfile
    image: my_username/medusa_storefront
    container_name: storefront
    depends_on:
      - backend
    environment:
      PORT: 8000
    ports:
      - "8000:8000"
    networks:
      - alpha_solutions_docker_network
    restart: always

  solr:
    image: solr
    container_name: solr
    depends_on:
      - postgres
    ports:
      - "8983:8983"
    volumes:
      - data:/var/solr
      - ./solr:/opt/solr/server/solr/configsets/product_index
    entrypoint:
      - docker-entrypoint.sh
      - solr-precreate
      - product_index
    networks:
      - alpha_solutions_docker_network
    restart: always
volumes:
  data:


networks:
  alpha_solutions_docker_network:

When running my medusa_backend in development mode via npm run start I can use my subscriber and it calls the function as intended. Note: the rest of the application (admin GUI, databases) is running in docker.

I am listening to the event "product.updated" and it gives the following response when running the backend in develop mode:

info: Processing product.updated which has 1 subscribers

When my Medusa backend (and rest of the application) is run via my docker-compose.yml file via "docker-compose up --build -d" and try to invoke the event I get the following response:

info: Processing product.updated which has 0 subscribers

At first I thought my docker containers were unable to connect to each other, but from the command line in my backend docker container I can go to the Redis server via "redis-cli -u $REDIS_URL" and execute the "ping" command. Which means that the Medusa_backend container can successfully connect using the $REDIS_URL env variable defined in my docker-compose.yml.

The big difference between running in development mode (npm start) and in docker is that the URL's for my Postgres, Redis and Solr is changed to their container names instead of localhost so that Docker can redirect to the proper IP.

Update When running the same Redis image in docker, but not as a part of the network, my backend can connect to it via localhost:6379.

Update 2 Turns out that as soon as I run the medusa_backend as a container in my I cannot use my subscriber. Thought it worked when running the image with a Redis server outside the docker network (via localhost). It did not. In the medusa_backend logs i can see:

info:    Processing product.updated which has 0 subscribers

I am truly confused as to why - but will keep looking into it. I assume it must be something with the connection the Redis database. Also I have added a check to my docker-compose file that verifies that my Redis is running before starting my Medusa_backend server.

Update 3 I tried to console.log my EventBusService inside my subscribers constructor. Running the Medusa_backend locally (via npm start) it logs a full eventbus object with connection parameters to my redis instance. When executed in the docker environment no eventbus is logged - which makes me wonder if the eventbus gets initialized at all.

Are there any known way to ensure the EventBusService is initialized when starting the backend?


Solution

  • SOLUTION

    I figured out a solution to my problem.

    When I realized that the Subscriber (and the eventBusService etc) was never initialized let me into the thought process that my project did not handle my TS files correctly.

    It turns out that my subscriber and service while written in TS was not transpiled/compiled as expected.

    Then I looked into MedusaJS and TypeScript and found a PR that added support for TS.

    I then decided to read through the changes and add the ones relevant for my project (for now).

    I updated my package.json file with a build script:

    "scripts": {
    "build": "tsc -p tsconfig.json",
    "start": "npm run build && medusa develop"
    },
    

    I added the following to the my tsconfig.json

    {
      "compilerOptions": {
        "experimentalDecorators": true,
      },
      "extends": "./tsconfig.base.json",
      "include": ["src"],
      "exclude": ["node_modules", "**/*.spec.ts"]
    }
    

    I added a tsconfig.base.json file

    {
        "compilerOptions": {
          "lib": ["es5", "es6"],
          "target": "esnext",
          "allowJs": true,
          "esModuleInterop": false,
          "module": "commonjs",
          "moduleResolution": "node",
          "emitDecoratorMetadata": true,
          "experimentalDecorators": true,
          "skipLibCheck": true,
          "skipDefaultLibCheck": true,
          "declaration": false,
          "sourceMap": false,
          "outDir": "./dist",
          "rootDir": "src",
          "baseUrl": "src"
        },
        "exclude": ["node_modules"]
      }
    

    I updated my [develop.sh](http://develop.sh) script to run the same commandos as the npm start script

    medusa migrations run
    
    npm run build
    
    medusa develop
    

    Then I ran my docker commands

    docker-compose up --build -d

    Boom. The Medusa_backend log showcased that the Subscriber was initialized and the subscriber worked as intended.