3

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?

filpa
  • 3,651
  • 8
  • 52
  • 91
  • 1
    Correct me if I got it wrong, you want to get `books-service.1.zabvo1jal0h2xya9qfftnrnej` from inside the container, right? Or just part of the name? – anemyte Mar 15 '21 at 10:17
  • 1
    Yes, that is correct. More specifically, I want to get that value so that I can extract the `books-service.1` part. If there is a way of getting `books-service.1` directly, that would be fine too. If there is a way to get the `1` by itself, *that* would be fine too. – filpa Mar 15 '21 at 14:46

1 Answers1

3

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.

anemyte
  • 17,618
  • 1
  • 24
  • 45
  • *Exactly* what I needed - although `task` is mentioned in the docs, I wasn't quite able to make the connection. Happy to give you the bounty as soon as it is eligible. Cheers! – filpa Mar 15 '21 at 17:47
  • On a separate note, I do wish that the last column in `docker ps` was called `TASK NAMES` instead. That would've saved me quite a bit of time. :) – filpa Mar 15 '21 at 17:49
  • @user991710 to tell the truth I had somewhat the same problem with the TASK_SLOT. I had to test experimentally to check if it is what I think it is. – anemyte Mar 16 '21 at 06:24
  • 1
    There is a 1:1 binding between a task and a container. `docker ps` provides a container view, in case of swarm services it shows the container created by a task.The task names are shown by `docker service ps ${servicename}` in the NAME column. – Metin Mar 20 '21 at 14:09