docker api

whenever you run something like docker run ... underneath it just performs rest api call to local docker daemon

by default on macos daemon listens not for some port as we used to but for /var/run/docker.sock unix socket

here you can find bunch of useful examples and here is few of them

print version and info

curl -s --unix-socket /var/run/docker.sock http://localhost/version | jq
curl -s --unix-socket /var/run/docker.sock http://localhost/info | jq

create container (docs)

curl -s -X POST --unix-socket /var/run/docker.sock -d '{"Image":"nginx:latest"}' -H 'Content-Type: application/json' http://localhost/containers/create?name=nginx | jq

start container

curl -s -X POST --unix-socket /var/run/docker.sock -H 'Content-Type: application/json' http://localhost/containers/543d296c04eb16287dead09077592e1cb321f26fce50547618f87c74b0d449f5/start

list containers

curl -s --unix-socket /var/run/docker.sock -H 'Content-Type: application/json' http://localhost/containers/json | jq

container details

curl -s --unix-socket /var/run/docker.sock -H 'Content-Type: application/json' http://localhost/containers/543d296c04eb16287dead09077592e1cb321f26fce50547618f87c74b0d449f5/json | jq

with that in place we can have something like:

const http = require('http')

const request = (path, body = null, method = 'GET') => new Promise((resolve) => http.request({
    socketPath: '/var/run/docker.sock',
    headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
    },
    method: body && method === 'GET' ? 'POST' : method,
    path
}, response => {
    let body = ''
    response.setEncoding('utf-8')
    response.on('data', chunk => body += chunk)
    response.on('end', () => resolve(body ? JSON.parse(body) : null))
}).end(body ? JSON.stringify(body) : undefined))

module.exports = {
    version: () => request('/version'),
    info: () => request('/info'),
    create: (name, image) => request(`/containers/create?name=${name}`, {Image: image}),
    start: (id) => request(`/containers/${id}/start`, null, 'POST'),
    list: () => request(`/containers/json`),
    details: (id) => request(`/containers/${id}/json`),
    stats: (id) => request(`/containers/${id}/stats?stream=false`),
    stop: (id) => request(`/containers/${id}/stop`, null, 'POST'),
    remove: (id) => request(`/containers/${id}`, null, 'DELETE'),
}

which will allow us to do something like:

const docker = require('./docker')

docker.create('nginx', 'nginx').then(({Id}) => {
    docker.start(Id).then(() => {
        docker.details(Id).then(details => {
            console.log(details)
            docker.stop(Id).then(() => {
                docker.remove(Id).then(() => {
                    console.log('done')
                })
            })
        })
    })
})

Kubernetes Resourses Note

All this note is quite usefull to describe how Kubernetes resources requests and limits works

At the very end, each server has not only docker but also kubelet (aka our simplified api)

With help of such api kubernetes scheduler can understand how much of resources available/used on each server

And whenver we as users ask kubernetes to create new pods in cluster it will look for server that has enought free resourses to fit our requests

Kubernetes resourses requests themselves DO NOT affect actual usage it is just a hint for scheduler to do it work

It is a bad idea to lie about resources usage and requests should be as close as possible to actual usage to avoid OOM or throttles