Reliable way of getting the full container name inside a container running in Docker Swarm

Viewed 253

Background: I have a setup where many different scalable services connect to their databases via a connection pool (per instance). These services run within a Docker Swarm.

In my current database setup, this ends up looking as follows (using PostgreSQL in this example):

PID | Database | User | Application                     | Client | ...
... | db1      | app  | --standard JDBC driver string-- | x      | ...
... | db1      | app  | --standard JDBC driver string-- | y      | ... 
... | db1      | app  | --standard JDBC driver string-- | y      | ... 
... | ...      | app  | ...                             | x      | ... 
... | ...      | app  | ...                             | x      | ... 
... | db2      | app  | --standard JDBC driver string-- | y      | ... 
... | db2      | app  | --standard JDBC driver string-- | y      | ... 
... | ...      | app  | ...                             | x      | ... 
... | ...      | app  | ...                             | x      | ... 

What I would like to do, effectively, is provide the current Docker Swarm container name, including scaling identifier, to the DBMS to be able to better monitor the database connections, i.e.:

PID | Database | User | Application        | Client | ...
... | db1      | app  | books-service.1    | x      | ...
... | db1      | app  | books-service.2    | y      | ... 
... | db1      | app  | books-service.3    | y      | ... 
... | ...      | app  | ...                | x      | ... 
... | ...      | app  | ...                | x      | ... 
... | db2      | app  | checkout-service.2 | y      | ... 
... | db2      | app  | checkout-service.2 | y      | ... 
... | ...      | app  | ...                | x      | ... 
... | ...      | app  | ...                | x      | ... 

(obviously, setting the connection string is trivial - it's getting the information to set that is the issue)

Since my applications are managed by Docker Swarm (and sometime in the future, likely Kubernetes), I cannot manually set this value via environment (as I do not perform a docker run).

When running docker ps on a given Swarm node, I see the following output:

CONTAINER ID        IMAGE                                               COMMAND                  CREATED             STATUS              PORTS                                 NAMES
59cdbf724091        my-docker-registry.net/books-service:latest         "/bin/sh -c '/usr/bi…"   7 minutes ago       Up 7 minutes                                              books-service.1.zabvo1jal0h2xya9qfftnrnej
0eeeee15e92a        my-docker-registry.net/checkout-service:latest      "/bin/sh -c 'exec /u…"   8 minutes ago       Up 8 minutes                                              checkout-service.2.189s7d09m0q86y7fdf3wpy0vc

Of note is the NAMES column, which includes an identifier for the actual instance of the given container (or image, however you'd prefer to look at it). Do note that this name is not the hostname of the container, which by default is the container ID.

I know there are ways to determine if an application is running inside Docker (e.g. using /proc/1/cgroup), but that doesn't help me either as those also only list the container ID.

Is there a way to get this value from inside a Docker container that is being run in a swarm?

1 Answers

What you need (books-service.1) is a combination of a swarm service name and a task slot. Both of these can be passed to the container as environment variables, as well as a full task name (books-service.1.zabvo1jal0h2xya9qfftnrnej):

version: "3.0"
services:
  test:
    image: debian:buster
    command: cat /dev/stdout
    environment:
      SERVICE_NAME: '{{ .Service.Name }}'
      TASK_SLOT: '{{ .Task.Slot }}'
      TASK_NAME: "{{ .Task.Name }}"

After passing these you can either strip the TASK_NAME to get what you need or combine the SERVICE_NAME with the TASK_SLOT. Come to think of it, you can combine them right in the template:

version: "3.0"
services:
  test:
    image: debian:buster
    command: cat /dev/stdout
    environment:
      MY_NAME: '{{ .Service.Name }}.{{.Task.Slot}}'

Other possible placeholders can be found here.

Related