Swiftorial Logo
Home
Swift Lessons
Tutorials
Learn More
Career
Resources

Docker API

The Docker API allows you to interact with the Docker engine programmatically, enabling automation and integration with other tools and services. This guide covers key concepts, steps to use the Docker API, examples, and best practices for using the Docker API with Express.js applications.

Key Concepts of Docker API

  • RESTful Interface: The Docker API is a RESTful API that allows you to manage Docker resources using HTTP requests.
  • Endpoints: The Docker API provides various endpoints to interact with Docker containers, images, volumes, networks, and more.
  • Authentication: Secure access to the Docker API using authentication mechanisms such as TLS.
  • Docker SDKs: Use Docker SDKs for different programming languages to simplify interactions with the Docker API.

Setting Up the Project

Initialize a new Express.js project and create a Dockerfile:

// Initialize a new project
// npm init -y

// Install Express and Axios
// npm install express axios

// Create the project structure
// mkdir src
// touch src/index.js Dockerfile .dockerignore .gitignore

// .gitignore
node_modules
.env

// .dockerignore
node_modules
npm-debug.log

Creating an Express Application

Create a simple Express application that interacts with the Docker API:

Example: index.js

// src/index.js
const express = require('express');
const axios = require('axios');
const app = express();
const port = 3000;

// Docker API endpoint
const DOCKER_API_URL = 'http://localhost:2375';

// List all Docker containers
app.get('/containers', async (req, res) => {
    try {
        const response = await axios.get(`${DOCKER_API_URL}/containers/json`);
        res.json(response.data);
    } catch (error) {
        res.status(500).send('Error fetching containers');
    }
});

// Start a new Docker container
app.post('/containers/start', async (req, res) => {
    try {
        const response = await axios.post(`${DOCKER_API_URL}/containers/create`, {
            Image: 'alpine',
            Cmd: ['echo', 'Hello, Docker API!']
        });
        await axios.post(`${DOCKER_API_URL}/containers/${response.data.Id}/start`);
        res.send('Container started');
    } catch (error) {
        res.status(500).send('Error starting container');
    }
});

app.listen(port, () => {
    console.log(`Server running at http://localhost:${port}/`);
});

Creating a Dockerfile

Create a Dockerfile to containerize your Express application:

Example: Dockerfile

// Dockerfile
FROM node:14

# Create app directory
WORKDIR /usr/src/app

# Install app dependencies
COPY package*.json ./
RUN npm install

# Bundle app source
COPY . .

# Expose port 3000 to the outside world
EXPOSE 3000

# Run app when the container launches
CMD ["node", "src/index.js"]

Building and Running the Docker Container

Build and run the Docker container for your Express application:

// Build the Docker image
docker build -t my-express-app .

// Run the Docker container
docker run -d -p 3000:3000 --name my-express-app my-express-app

// Open http://localhost:3000/containers to list all Docker containers

Using Docker SDKs

Use Docker SDKs to simplify interactions with the Docker API:

Example: Using the Dockerode SDK

// Install Dockerode
// npm install dockerode

// src/index.js
const express = require('express');
const Docker = require('dockerode');
const app = express();
const port = 3000;

// Initialize Dockerode
const docker = new Docker({ socketPath: '/var/run/docker.sock' });

// List all Docker containers
app.get('/containers', async (req, res) => {
    try {
        const containers = await docker.listContainers();
        res.json(containers);
    } catch (error) {
        res.status(500).send('Error fetching containers');
    }
});

// Start a new Docker container
app.post('/containers/start', async (req, res) => {
    try {
        const container = await docker.createContainer({
            Image: 'alpine',
            Cmd: ['echo', 'Hello, Docker API!']
        });
        await container.start();
        res.send('Container started');
    } catch (error) {
        res.status(500).send('Error starting container');
    }
});

app.listen(port, () => {
    console.log(`Server running at http://localhost:${port}/`);
});

Authenticating to the Docker API

Secure access to the Docker API using TLS:

Example: Docker API with TLS

// Generate server and client certificates
// openssl genrsa -aes256 -out ca-key.pem 2048
// openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem
// openssl genrsa -out server-key.pem 2048
// openssl req -subj "/CN=localhost" -new -key server-key.pem -out server.csr
// echo subjectAltName = DNS:localhost,IP:127.0.0.1,IP:192.168.1.101 > extfile.cnf
// echo extendedKeyUsage = serverAuth >> extfile.cnf
// openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extfile extfile.cnf
// openssl genrsa -out key.pem 2048
// openssl req -subj '/CN=client' -new -key key.pem -out client.csr
// echo extendedKeyUsage = clientAuth > extfile-client.cnf
// openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out cert.pem -extfile extfile-client.cnf

// Configure Docker daemon with TLS
{
  "hosts": ["tcp://0.0.0.0:2376"],
  "tls": true,
  "tlsverify": true,
  "tlscacert": "/etc/docker/ca.pem",
  "tlscert": "/etc/docker/server-cert.pem",
  "tlskey": "/etc/docker/server-key.pem"
}

// Restart Docker daemon
systemctl restart docker

Example: Connecting to Docker API with TLS

// src/index.js
const express = require('express');
const fs = require('fs');
const axios = require('axios');
const https = require('https');
const app = express();
const port = 3000;

// Docker API endpoint with TLS
const DOCKER_API_URL = 'https://localhost:2376';
const httpsAgent = new https.Agent({
    ca: fs.readFileSync('/path/to/ca.pem'),
    cert: fs.readFileSync('/path/to/cert.pem'),
    key: fs.readFileSync('/path/to/key.pem')
});

// List all Docker containers
app.get('/containers', async (req, res) => {
    try {
        const response = await axios.get(`${DOCKER_API_URL}/containers/json`, { httpsAgent });
        res.json(response.data);
    } catch (error) {
        res.status(500).send('Error fetching containers');
    }
});

// Start a new Docker container
app.post('/containers/start', async (req, res) => {
    try {
        const response = await axios.post(`${DOCKER_API_URL}/containers/create`, {
            Image: 'alpine',
            Cmd: ['echo', 'Hello, Docker API!']
        }, { httpsAgent });
        await axios.post(`${DOCKER_API_URL}/containers/${response.data.Id}/start`, {}, { httpsAgent });
        res.send('Container started');
    } catch (error) {
        res.status(500).send('Error starting container');
    }
});

app.listen(port, () => {
    console.log(`Server running at http://localhost:${port}/`);
});

Best Practices for Docker API

  • Secure the API: Always secure the Docker API with TLS and proper authentication mechanisms.
  • Limit API Access: Restrict access to the Docker API to trusted users and systems only.
  • Use SDKs: Use Docker SDKs for different programming languages to simplify interactions with the Docker API.
  • Handle Errors Gracefully: Implement proper error handling in your application when interacting with the Docker API.
  • Monitor API Usage: Continuously monitor and audit the usage of the Docker API to detect any unauthorized access or misuse.

Testing Docker API

Test your Docker API integrations to ensure they work correctly:

Example: Testing with Mocha and Chai

// Install Mocha and Chai
// npm install --save-dev mocha chai

// test/app.test.js
const chai = require('chai');
const expect = chai.expect;
const axios = require('axios');

describe('Express App', () => {
    it('should return a list of Docker containers', async () => {
        const response = await axios.get('http://localhost:3000/containers');
        expect(response.data).to.be.an('array');
    });

    it('should start a new Docker container', async () => {
        const response = await axios.post('http://localhost:3000/containers/start');
        expect(response.status).to.equal(200);
        expect(response.data).to.equal('Container started');
    });
});

// Add test script to package.json
// "scripts": {
//   "test": "mocha"
// }

// Run tests
// docker build -t my-express-app .
// docker run -p 3000:3000 my-express-app
// npm test

Key Points

  • RESTful Interface: The Docker API is a RESTful API that allows you to manage Docker resources using HTTP requests.
  • Endpoints: The Docker API provides various endpoints to interact with Docker containers, images, volumes, networks, and more.
  • Authentication: Secure access to the Docker API using authentication mechanisms such as TLS.
  • Docker SDKs: Use Docker SDKs for different programming languages to simplify interactions with the Docker API.
  • Follow best practices for Docker API, such as securing the API, limiting API access, using SDKs, handling errors gracefully, and monitoring API usage.

Conclusion

The Docker API allows you to interact with the Docker engine programmatically, enabling automation and integration with other tools and services. By understanding and implementing the key concepts, steps, examples, and best practices covered in this guide, you can effectively use the Docker API with Express.js applications. Happy coding!