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: bridgeIn this setup, frontend-app can reach
backend-api by addressing
http://backend-api:5000.
Key Considerations and Troubleshooting
- Internal vs. Published Ports: Use the port that the
target application is listening on inside the container (defined by
expose), not the external port mapped to the host (defined byports). - Shared Network Requirement: Containers must be attached to the same Docker network to resolve each other's hostnames.
- Server-Side vs. Client-Side Execution: Axios requests configured with internal container hostnames will only work when executed server-side (e.g., inside a Node.js runtime). If Axios runs in a user's browser, it cannot resolve internal Docker hostnames and must target a publicly accessible domain or host port instead.