Skip to content

Instantly share code, notes, and snippets.

@melvz
Last active October 24, 2018 05:31
Show Gist options
  • Save melvz/086f0c16034e7e1488988fc3af7d7778 to your computer and use it in GitHub Desktop.
Save melvz/086f0c16034e7e1488988fc3af7d7778 to your computer and use it in GitHub Desktop.

Exposing the remote API of a Docker container

Context

In case you find yourself using NodeJS for backend scripting, you can use the power of API calls to manage your Docker containers.

Docker has shell bin commands but it's nice to know the remote API calls so an application can remotely control your containers. This document shows how to setup your docker service (inside Centos 7) to expose the API port.

Make sure your docker service is running as a systemd service.

Use the systemctl command to check the status of the DOcker service in Centos7:


# systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor preset: disabled)
   Active: active (running) since Mon 2018-08-06 06:53:00 UTC; 2h 7min ago
     Docs: https://docs.docker.com
 Main PID: 12949 (dockerd)
    Tasks: 41
   Memory: 218.0M
   CGroup: /system.slice/docker.service
           ├─12949 /usr/bin/dockerd -H tcp://0.0.0.0:4243 -H unix:///var/run/docker.sock
           ├─12955 docker-containerd --config /var/run/docker/containerd/containerd.toml
           ├─13222 docker-containerd-shim -namespace moby -workdir /var/lib/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/407c347e14f04e8c5ec1eb3...
           └─17313 docker-containerd-shim -namespace moby -workdir /var/lib/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/fbdf97a79ab754c939fae54...

Take note that above output reveals your service runs from config file location: /usr/lib/systemd/system/docker.service

So open up the config file (/usr/lib/systemd/system/docker.service) and find the line: "ExecStart" .


[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target

[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:4243 -H unix:///var/run/docker.sock
ExecReload=/bin/kill -s HUP $MAINPID
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Uncomment TasksMax if your systemd version supports it.
# Only systemd 226 and above support this version.
#TasksMax=infinity
TimeoutStartSec=0
# set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes
# kill only the docker process, not all processes in the cgroup
KillMode=process
# restart the docker process if it exits prematurely
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s

[Install]
WantedBy=multi-user.target

The ExecStart line should appear like this:


ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:4243 -H unix:///var/run/docker.sock

So in the above line, you use ExecStart to define the endpoint at PORT 4243 to be exposed by the docker API. Ofcourse you can choose the port you wish.

Save and close the file.

Reload the OS service daemon and restart the docker service.


systemctl daemon-reload
systemctl restart docker

Test by calling your local docker API endpoint

Now focus on the output of the LAST column, and I know it is confusing but keep treading! The LAST column contains a 'k8s' character, and the POD name is the one with DASHES / HYPHENS. So parsing it from the example, the POD name is: mongodb-mongopop-2-ql797.




# curl http://localhost:4243/containers/json | python -m json.tool
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  3289    0  3289    0     0   334k      0 --:--:-- --:--:-- --:--:--  401k
[
    {
        "Command": "/docker-entrypoint.sh elasticsearch",
        "Created": 1533543913,
        "HostConfig": {
            "NetworkMode": "default"
        },
        "Id": "fbdf97a79ab754c939fae54ee070efa72d4d50b054664281aa05315b4e7414eb",
        "Image": "elasticsearch:2.4@sha256:c88b3a2e3d8329d1495f1ace838070cd310d24a1134ea57821011713f3701dfc",
        "ImageID": "sha256:5bcaa10a02c0d8f42accbe227611fa097c9a2d2347c5e3e5a2d0e441e43c28b3",
        "Labels": {
            "com.docker.swarm.node.id": "uunb9k35hudmxx5hn2771cogr",
            "com.docker.swarm.service.id": "j7h8z8hz52pigpgiw271lymc8",
            "com.docker.swarm.service.name": "elasticsearch",
            "com.docker.swarm.task": "",
            "com.docker.swarm.task.id": "6eqaohuzwsm7987tq46uq3oeu",
            "com.docker.swarm.task.name": "elasticsearch.1.6eqaohuzwsm7987tq46uq3oeu"
        },
        "Mounts": [
            {
                "Destination": "/usr/share/elasticsearch/data",
                "Driver": "local",
                "Mode": "",
                "Name": "dcaf16870b94e0d3f0967331ff3214700c633435664177cb9fe6641504801874",
                "Propagation": "",
                "RW": true,
                "Source": "",
                "Type": "volume"
            }
        ],
        "Names": [
            "/elasticsearch.1.6eqaohuzwsm7987tq46uq3oeu"
        ],
        "NetworkSettings": {
            "Networks": {
                "elk": {
                    "Aliases": null,
                    "DriverOpts": null,
                    "EndpointID": "bc55fbd7bbfbee8c8a5ffbf5ddc95bda70adaa9a5c03a6735cacd8f191270186",
                    "Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "IPAMConfig": {
                        "IPv4Address": "10.0.1.4"
                    },
                    "IPAddress": "10.0.1.4",
                    "IPPrefixLen": 24,
                    "IPv6Gateway": "",
                    "Links": null,
                    "MacAddress": "02:42:0a:00:01:04",
                    "NetworkID": "o850lapb8guatmwox6rjug4p5"
                },
                "ingress": {
                    "Aliases": null,
                    "DriverOpts": null,
                    "EndpointID": "46945fda83cbc104ecef504a785f7760a6639dc889154efd71ed040b03b6fa4b",
                    "Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "IPAMConfig": {
                        "IPv4Address": "10.255.0.6"
                    },
                    "IPAddress": "10.255.0.6",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "Links": null,
                    "MacAddress": "02:42:0a:ff:00:06",
                    "NetworkID": "hypp4uw933aur1m8u6sgsesxx"
                }
            }
        },
        "Ports": [
            {
                "PrivatePort": 9200,
                "Type": "tcp"
            },
            {
                "PrivatePort": 9300,
                "Type": "tcp"
            }
        ],
        "State": "running",
        "Status": "Up About an hour"
    },
    {
        "Command": "/entrypoint.sh /etc/docker/registry/config.yml",
        "Created": 1533538380,
        "HostConfig": {
            "NetworkMode": "default"
        },
        "Id": "407c347e14f04e8c5ec1eb3613183f6975092d245b9a236c8aa8954a28e542fb",
        "Image": "registry:2.5@sha256:d67ec9df3da06cac40fa2e56efb4371743dd7e952b57044c6b52f867795c645e",
        "ImageID": "sha256:f0e8149406ea879d0d957cc71be63c472ad638022ef880bb9ce6ab5e7882bac4",
        "Labels": {
            "com.docker.swarm.node.id": "uunb9k35hudmxx5hn2771cogr",
            "com.docker.swarm.service.id": "ai28gnve1y8kuk19qbthlkj74",
            "com.docker.swarm.service.name": "registry",
            "com.docker.swarm.task": "",
            "com.docker.swarm.task.id": "zovn7lds6hwrjxufl64z89hge",
            "com.docker.swarm.task.name": "registry.1.zovn7lds6hwrjxufl64z89hge"
        },
        "Mounts": [
            {
                "Destination": "/var/lib/registry",
                "Driver": "local",
                "Mode": "",
                "Name": "75cf82de864acf3caee558bf98685c7ff2447da1dd997447d9679d1ad659a5d0",
                "Propagation": "",
                "RW": true,
                "Source": "",
                "Type": "volume"
            }
        ],
        "Names": [
            "/registry.1.zovn7lds6hwrjxufl64z89hge"
        ],
        "NetworkSettings": {
            "Networks": {
                "ingress": {
                    "Aliases": null,
                    "DriverOpts": null,
                    "EndpointID": "52c2ac66b0d38bb0376242fea42e4a3e93797df7e87a805e9f8d88dc35b2150c",
                    "Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "IPAMConfig": {
                        "IPv4Address": "10.255.0.4"
                    },
                    "IPAddress": "10.255.0.4",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "Links": null,
                    "MacAddress": "02:42:0a:ff:00:04",
                    "NetworkID": "hypp4uw933aur1m8u6sgsesxx"
                }
            }
        },
        "Ports": [
            {
                "PrivatePort": 5000,
                "Type": "tcp"
            }
        ],
        "State": "running",
        "Status": "Up 2 hours"
    }
]
[root@ip-172-31-37-63 today]#



Now you see the value of API XGET calls. So whenever an application calls the API endpoint URL, you get a JSON output, which you can parse and use for report-generation.

Reference / Further research:

https://stackoverflow.com/questions/40242522/how-do-i-expose-the-docker-remote-api-on-centos-7 https://blog.flux7.com/blogs/docker/docker-tutorial-series-part-8-docker-remote-api

~

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment