How to Use Axios with Docker Container Hostnames

Connecting an application to other services inside a Docker network requires routing requests through Docker's internal DNS rather than standard public endpoints. This guide explains how Docker resolves container service names as hostnames and details how to configure the Axios HTTP client using custom instances and environment variables to reliably make internal HTTP requests between containers.

Understanding Docker Internal Networking

When multiple containers run within the same user-defined bridge network (or within the same docker-compose environment), Docker's embedded DNS server automatically maps container names and Compose service names to their respective internal IP addresses.

Inside a container, localhost refers exclusively to the container itself, not the host machine or neighboring containers. To send an HTTP request from one container to another, Axios must target the destination container's service name and its internal exposed port.

Configuring Axios

The cleanest way to handle internal container communication in Axios is by creating a dedicated Axios instance using axios.create() and managing the hostnames via environment variables.

1. Define the Environment Variable

Avoid hardcoding internal hostnames directly into your application code. Use an environment variable to define the base URL:

API_SERVICE_URL=http://backend-api:5000

2. Create the Axios Instance

Set up an Axios client that utilizes the internal service hostname as its baseURL:

const axios = require('axios');

const apiClient = axios.create({
  baseURL: process.env.API_SERVICE_URL || 'http://backend-api:5000',
  timeout: 5000,
  headers: {
    'Content-Type': 'application/json',
  },
});

// Example request to http://backend-api:5000/users
async function fetchUsers() {
  try {
    const response = await apiClient.get('/users');
    return response.data;
  } catch (error) {
    console.error('Error fetching data from internal service:', error.message);
    throw error;
  }
}

module.exports = apiClient;

Docker Compose Example

To ensure the hostname resolves correctly, both the client container and the target container must share the same network.

version: '3.8'

services:
  frontend-app:
    build: ./frontend
    environment:
      - API_SERVICE_URL=http://backend-api:5000
    networks:
      - app-network
    depends_on:
      - backend-api

  backend-api:
    build: ./backend
    expose:
      - "5000"
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

In this setup, frontend-app can reach backend-api by addressing http://backend-api:5000.

Key Considerations and Troubleshooting