node.jsdockerexpressprintingthermal-printer

How to Combine Host Network with Docker to Resolve IP Connectivity Issues?


I am working on dockerizing my POS system, but I've encountered a challenge. In my setup, I usually store the printer's IP address in the product table of the database, as some products need to be printed on specific thermal printers.

However, after dockerizing the system, the printers are not working. While the data is successfully created in the database, the printers no longer print anything, even though they used to work fine before dockerization.

Here is my Dockerfile:

# Base image 
FROM node:21-slim

# Set working directory 
WORKDIR /app

# Copy package.json and install dependencies 
COPY package*.json ./ 

RUN npm uninstall bcrypt 

RUN npm install pm2 -g && npm install bcrypt && npm install

# Copy application files 
COPY . .

# Copy Prisma schema directory 
COPY prisma ./prisma

# Install required dependencies 
RUN apt-get update -y && apt-get install -y openssl

# Generate Prisma client 
RUN npx prisma generate

# Expose the app's port 
EXPOSE 4000

# Start the app with PM2 
CMD ["pm2-runtime", "ecosystem.config.js"]

docker-compose.yml:

    build:
      context: .
      dockerfile: Dockerfile
    container_name: pos
    ports:
      - "4000:4000"
    env_file:
      - .env
    environment:
      DATABASE_URL: "mysql://root:${DATABASE_PASSWORD}@${IP_ADDRESS}:3306/${DATABASE_NAME}?connection_limit=150&pool_timeout=20"
      ACCESS_TOKEN: "37eb2d015162e05553cae95588485f3b18de5eb95182c97fc0df8293222010028d797515afefbb72b861c637c1288987e3628ed8103641eb53d439e630a90a6d"
      ADMIN_PORT: 4500
      PORT: 4000
      REDIS_URL: "redis://redis:6379"
    depends_on:
      - redis


  redis:
    image: redis:alpine
    container_name: redis ```

Im using tcpIp technique to send orders to printers (node-thermal-printer package): ```
      let printer = new ThermalPrinter({
        type: PrinterTypes.TANCA,
        interface: "tcp://" + printerIp,
        width: 40,
        options: { timeout: 5000 }
      }); 

I have successfully pinged the printer's IP from the Docker container. I also tried setting the network_mode to host in the app's configuration, but this caused a conflict between the app and Redis, as both are on the same network. When I changed the app to use the host network mode, I had to modify the Redis configuration, which I do not want to do.

This one doesn't work as well:

network_mode: "host"
environment:
  REDIS_URL: "redis://172.18.0.2:6379" //CONTAINER'S IP

Solution

  • I managed to fix the issue by following these steps:

    1- Modified the docker-compose.yml file to this one:

     services:
       app:
         build:
           context: .
           dockerfile: Dockerfile
         container_name: pos
         ports:
           - "4000:4000"
         env_file:
           - .env
         environment:
           DATABASE_URL: "mysql://root:${DATABASE_PASSWORD}@host.docker.internal:3306/${DATABASE_NAME}?connection_limit=150&pool_timeout=20"
           ACCESS_TOKEN: "37eb2d015162e05553cae95588485f3b18de5eb95182c97fc0df8293222010028d797515afefbb72b861c637c1288987e3628ed8103641eb53d439e630a90a6d"
           ADMIN_PORT: 4500
           PORT: 4000
           REDIS_URL: "redis://redis:6379" # Use service name "redis" for inter-container communication
         depends_on:
           - redis # Ensure Redis starts before the app
         networks:
           - app-network
         volumes:
           - pos:/app
    
       redis:
         image: redis:alpine
         container_name: redis
         networks:
           - app-network
    
     networks:
       app-network:
         driver: bridge
    
     volumes:
       pos:
    

    2- And then pinged to the printer from the docker container through these steps:

    Access the container:

    docker exec -it <container_name_or_id> /bin/bash
    

    Determine OS:

    cat /etc/os-release
    

    In my case it's debian, so I just installed necessary packages to ping the printer's IP address:

    apt-get update && apt-get install -y iputils-ping
    

    Then pinged the IP:

    ping 192.168.1.100
    

    All requests reached successfully.

    exit the container

    exit
    

    3- Then modified the Dockerfile, installed some required libraries and packages to my container in order to be able to run Puppeteer and headless browser (I used in the vouchers):

    # Base image
    FROM node:21-slim
    
    RUN apt-get update && apt-get install -y \
        libglib2.0-0 \
        libnss3 \
        libatk1.0-0 \
        libatk-bridge2.0-0 \
        libcups2 \
        libdrm2 \
        libxkbcommon0 \
        libxcomposite1 \
        libxdamage1 \
        libxfixes3 \
        libxrandr2 \
        libgbm1 \
        libgtk-3-0 \
        libasound2 \
        libxshmfence1 \
        chromium \
        && rm -rf /var/lib/apt/lists/*
    
    # Set working directory
    WORKDIR /app
    
    # Copy package.json and install dependencies
    COPY package*.json ./
    
    RUN npm install pm2 -g && npm install bcrypt && npm install
    
    # Copy application files
    COPY . .
    
    # Copy Prisma schema directory
    COPY prisma ./prisma
    
    # Install required dependencies
    RUN apt-get update -y && apt-get install -y openssl
    
    # Generate Prisma client
    RUN npx prisma generate
    
    # Expose the app's port
    EXPOSE 4000
    
    # Start the app with PM2
    CMD ["pm2-runtime", "ecosystem.config.js"]