Connect Axios to Unix Domain Sockets in Node.js

Communicating over Unix domain sockets instead of standard TCP/IP ports offers significant performance and security benefits for local inter-process communication in Node.js. This article explains how to configure the Axios HTTP client to send requests through Unix domain sockets using native configuration parameters and custom HTTP agents, illustrated with practical code examples such as interacting with the Docker daemon.


Understanding Unix Domain Sockets in Axios

A Unix domain socket (UDS) allows bidirectional data exchange between processes running on the same host operating system without the overhead of network routing. Node.js's underlying http and https modules natively support Unix domain sockets via the socketPath option. Because Axios relies on these standard Node.js modules for transport, you can pass socket paths directly through Axios request configs.


Method 1: Using the Native socketPath Configuration

The most straightforward way to route requests through a socket is by defining the socketPath property in the Axios configuration object.

const axios = require('axios');

async function querySocket() {
  try {
    const response = await axios.get('http://localhost/info', {
      socketPath: '/var/run/my-service.sock'
    });

    console.log(response.data);
  } catch (error) {
    console.error('Request failed:', error.message);
  }
}

querySocket();

When socketPath is provided:


Practical Example: Interacting with the Docker Engine API

A common use case for Unix sockets in Node.js is communicating directly with the Docker daemon located at /var/run/docker.sock.

const axios = require('axios');

const dockerClient = axios.create({
  socketPath: '/var/run/docker.sock',
  baseURL: 'http://localhost/v1.41'
});

async function listContainers() {
  try {
    const response = await dockerClient.get('/containers/json');
    console.log('Running containers:', response.data);
  } catch (error) {
    console.error('Error fetching containers:', error.message);
  }
}

listContainers();

Method 2: Using a Custom http.Agent

For advanced connection pooling, timeouts, or specific keep-alive configurations, you can instantiate a custom Node.js http.Agent with the socketPath option and assign it to the Axios httpAgent property.

const axios = require('axios');
const http = require('http');

const agent = new http.Agent({
  socketPath: '/tmp/custom-app.sock',
  keepAlive: true,
  maxSockets: 10
});

const client = axios.create({
  httpAgent: agent,
  baseURL: 'http://unix'
});

async function sendPostRequest() {
  try {
    const response = await client.post('/api/data', {
      payload: 'sample data'
    });
    console.log('Response:', response.data);
  } catch (error) {
    console.error('Agent request failed:', error.message);
  }
}

sendPostRequest();

Key Considerations

  1. File Permissions: Ensure the Node.js process has read and write permissions for the specified .sock file path.
  2. Platform Differences: Unix domain sockets are native to POSIX systems (Linux, macOS). On Windows, named pipes (e.g., \\\\.\\pipe\\docker_engine) are used similarly through the socketPath parameter.
  3. URL Schemes: Always specify http:// as the protocol in your URL. Even though communication travels over a local socket, the data payload remains standard HTTP.