Docker : le sixième pas.

Attention ceci est mon brouillon avant de faire une belle documentation sur Docker (il y a à boire et à manger). 

On passe donc à l’étape de l’installation de HAProxy, l’installation cible est la suivante (il va falloir que j’améliore mon server.c (que l’on va appeler server2.c) afin d’avoir une connexion avec la base de donnée):

Capture d’écran 2016-04-20 à 14.47.21Voici un nouveau server2.c , mais avant cela il faut installer le RPM qui permet de faire de dev :

[root@localhost ~]# yum install postgresql-devel

Pour compiler il va falloir appeler la librairie pq (pour postgresql), cela donne donc :

[root@localhost ~]# gcc -o server2 server2.c -lpq

J’ai donc ajouter dans le programme :
-un bout de code afin de voir quel est l’interface locale
-un bout de code afin de voir quel est l’ip locale.
-un bout de code pour couper la communication via QUIT, EXIT, CLOSE.
-un bout de code pour se connecter à la base de donnée.
-un bout de code pour avoir des informations via le telnet.

Le source :

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/un.h>
#include "libpq-fe.h"

#define MYPORT 80
#define BACKLOG 5
#define MAXCLIENTS 5
#define MAXDATASIZE 100

int
main (void)
{
  int sockfd = -1, new_fd, numbytes, highest = 0, i;
  int clients[MAXCLIENTS];
  char buffer[MAXDATASIZE];
  char localip[MAXDATASIZE];
  struct sockaddr_in my_addr, their_addr;
  socklen_t sin_size;
  struct timeval tv;
  fd_set readfds;
  const char *conninfo;
  PGconn *conn;
  PGresult *res;
  FILE *f;
  char line[100], *p, *c;
  const char *google_dns_server = "8.8.8.8";
  int dns_port = 53;
  struct sockaddr_in serv;
  int sock = socket (AF_INET, SOCK_DGRAM, 0);

  f = fopen ("/proc/net/route", "r");

  while (fgets (line, 100, f))
    {
      p = strtok (line, " \t");
      c = strtok (NULL, " \t");

      if (p != NULL && c != NULL)
	{
	  if (strcmp (c, "00000000") == 0)
	    {
	      printf ("Default interface is : %s \n", p);
	      break;
	    }
	}
    }

  if (sock < 0)
    {
      perror ("Socket error");
    }

  memset (&serv, 0, sizeof (serv));
  serv.sin_family = AF_INET;
  serv.sin_addr.s_addr = inet_addr (google_dns_server);
  serv.sin_port = htons (dns_port);

  int err = connect (sock, (const struct sockaddr *) &serv, sizeof (serv));

  struct sockaddr_in name;
  socklen_t namelen = sizeof (name);
  err = getsockname (sock, (struct sockaddr *) &name, &namelen);

  const char *p2 = inet_ntop (AF_INET, &name.sin_addr, localip, 100);

  if (p2 != NULL)
    {
      printf ("Local ip is : %s \n", localip);
    }
  else
    {
      //Some error
      printf ("Error number : %d . Error message : %s \n", errno,
	      strerror (errno));
      strcpy (localip, "Error");
    }

  close (sock);

  conninfo =
    "hostaddr=127.0.0.1 port=5432 dbname=postgres user=postgres password=password";

  if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
    {
      perror ("socket");
      exit (-1);
    }
  my_addr.sin_family = AF_INET;
  my_addr.sin_port = htons (MYPORT);
  my_addr.sin_addr.s_addr = INADDR_ANY;
  bzero (&(my_addr.sin_zero), 8);

  if (bind (sockfd, (struct sockaddr *) &my_addr, sizeof (struct sockaddr)) ==
      -1)
    {
      perror ("bind");
      exit (-1);
    }
  if (listen (sockfd, BACKLOG) == -1)
    {
      perror ("listen");
      exit (-1);
    }
  bzero (clients, sizeof (clients));
  highest = sockfd;
  while (1)
    {
      sin_size = sizeof (struct sockaddr_in);
      tv.tv_sec = 0;
      tv.tv_usec = 250000;
      FD_ZERO (&readfds);
      for (i = 0; i < MAXCLIENTS; i++) { if (clients[i] != 0) { FD_SET (clients[i], &readfds); } } FD_SET (sockfd, &readfds); if (select (highest + 1, &readfds, NULL, NULL, &tv) >= 0)
	{
	  if (FD_ISSET (sockfd, &readfds))
	    {
	      if ((new_fd =
		   accept (sockfd, (struct sockaddr *) &their_addr,
			   &sin_size)) == -1)
		{
		  perror ("ACCEPT");
		  continue;
		}
	      for (i = 0; i < MAXCLIENTS; i++) { if (clients[i] == 0) { clients[i] = new_fd; break; } } if (i != MAXCLIENTS) { if (new_fd > highest)
		    {
		      highest = clients[i];
		    }
		  printf ("Connexion received from %s (slot %i) ",
			  inet_ntoa (their_addr.sin_addr), i);
		  send (new_fd, "\nHELLO\n", 7, MSG_NOSIGNAL);
		}
	      else
		{
		  send (new_fd, "\nTOO MANY CLIENT\n", 17, MSG_NOSIGNAL);
		  close (new_fd);
		}
	    }
	  for (i = 0; i < MAXCLIENTS; i++)
	    {
	      if (FD_ISSET (clients[i], &readfds))
		{
		  if ((numbytes =
		       recv (clients[i], buffer, MAXDATASIZE, 0)) <= 0)
		    {
		      printf ("Connexion lost from slot %i", i);
		      close (clients[i]);
		      clients[i] = 0;
		    }
		  else
		    {
		      buffer[numbytes] = '\0';
		      printf ("Received from slot %i : %s", i, buffer);
		      if (strncmp (buffer, "POSTGRES", 6) == 0)
			{
			  conn = PQconnectdb (conninfo);
			  if (PQstatus (conn) != CONNECTION_OK)
			    {
			      fprintf (stderr,
				       "Connection to database failed: %s",
				       PQerrorMessage (conn));
			      send (new_fd, "\nDB KO\n", 7, MSG_NOSIGNAL);
			    }
			  else
			    {
			      send (new_fd, "\nDB OK\n", 7, MSG_NOSIGNAL);
			      /* INSERT CLIENT IP and timestamp */
			    }
			  PQfinish (conn);
			}
		      if ((strncmp (buffer, "QUIT", 4) == 0))
			{
			  printf ("Connexion QUIT from slot %i", i);
			  close (clients[i]);
			  clients[i] = 0;
			}
		      if ((strncmp (buffer, "EXIT", 4) == 0))
			{
			  printf ("Connexion EXIT from slot %i", i);
			  close (clients[i]);
			  clients[i] = 0;
			}
		      if ((strncmp (buffer, "CLOSE", 5) == 0))
			{
			  printf ("Connexion CLOSE from slot %i", i);
			  close (clients[i]);
			  clients[i] = 0;
			}
		      if ((strncmp (buffer, "INTERFACE", 9) == 0))
			{
			  send (new_fd, "\n", 1, MSG_NOSIGNAL);
			  send (new_fd, localip, strlen (localip),
				MSG_NOSIGNAL);
			  send (new_fd, "\n", 1, MSG_NOSIGNAL);
			}
		      if ((strncmp (buffer, "IP", 2) == 0))
			{
			  send (new_fd, "\n", 1, MSG_NOSIGNAL);
			  send (new_fd, p, strlen (p), MSG_NOSIGNAL);
			  send (new_fd, "\n", 1, MSG_NOSIGNAL);
			}
                      if ((strncmp (buffer, "DBCNX", 2) == 0))
                        {
                          send (new_fd, "\n", 1, MSG_NOSIGNAL);
                          send (new_fd, conninfo, strlen (conninfo), MSG_NOSIGNAL);
                          send (new_fd, "\n", 1, MSG_NOSIGNAL);
                        }
		    }
		}
	    }
	}
      else
	{
	  perror ("SELECT");
	  continue;
	}
    }
  return 0;
}

Un petit test, sur un terminal je lance mon ./server2 :

[root@localhost ~]# ./server2
Default interface is : enp0s3 
Local ip is : 192.168.10.159 
Connexion received from 127.0.0.1 (slot 0) Received from slot 0 : IP
Received from slot 0 : INTERFACE
Received from slot 0 : DB
Received from slot 0 : POSTGRES
Received from slot 0 : QUIT

Et sur l’autre terminal je fais mon telnet :

Capture d’écran 2016-04-20 à 15.37.53

Maintenant il faut faire le Dockerfile de notre nouvelle application de test.

[root@localhost ~]# cat Dockerfile
FROM fedora
MAINTAINER toto toto@cyber-neurones.org 
COPY ./server2 /sbin/server2
RUN dnf install postgresql -y
# Le port en ecoute 
EXPOSE 80 
# Pour lancer postgres 
CMD ["/sbin/server2"]

[root@localhost ~]# docker build -t my-server2 .
Sending build context to Docker daemon 81.41 kB
Step 1 : FROM fedora
 ---> ddd5c9c1d0f2
Step 2 : MAINTAINER toto toto@cyber-neurones.org
 ---> Using cache
 ---> bb6bc55cbbfc
Step 3 : COPY ./server2 /sbin/server2
 ---> Using cache
 ---> 9dc98bb8714f
Step 4 : RUN dnf install postgresql -y
 ---> Running in 6ecdbee5cb9d

Last metadata expiration check performed 0:00:40 ago on Fri Apr 15 02:43:33 2016.
Dependencies resolved.
================================================================================
 Package                Arch          Version              Repository      Size
================================================================================
Installing:
 postgresql             x86_64        9.4.7-1.fc23         updates        1.1 M
 postgresql-libs        x86_64        9.4.7-1.fc23         updates        240 k

Transaction Summary
================================================================================
Install  2 Packages

Total download size: 1.3 M
Installed size: 4.4 M
Downloading Packages:

--------------------------------------------------------------------------------
Total                                           5.7 kB/s | 1.3 MB     04:02     
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Installing  : postgresql-libs-9.4.7-1.fc23.x86_64                         1/2 
  Installing  : postgresql-9.4.7-1.fc23.x86_64                              2/2 
  Verifying   : postgresql-9.4.7-1.fc23.x86_64                              1/2 
  Verifying   : postgresql-libs-9.4.7-1.fc23.x86_64                         2/2 

Installed:
  postgresql.x86_64 9.4.7-1.fc23       postgresql-libs.x86_64 9.4.7-1.fc23      

Complete!
 ---> db3219dbae87
Removing intermediate container 6ecdbee5cb9d
Step 5 : EXPOSE 80
 ---> Running in 46227ce25198
 ---> 0ed57fe27084
Removing intermediate container 46227ce25198
Step 6 : CMD /sbin/server2
 ---> Running in 1da4a2133df3
 ---> 2b02e0bc8c6e
Removing intermediate container 1da4a2133df3
Successfully built 2b02e0bc8c6e

Et maintenant le moment de vérité, on fait le test de notre server2 :

[root@localhost ~]# docker run -p 80:80 --name my-server2.1 -d my-server2
d7d4cb51000828388a09e5648e5b92094e5a17298d799b63b41d9511129b6211
[root@localhost ~]# telnet 127.0.0.1 80
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.

HELLO
IP

eth0
INTERFACE

172.17.0.3
POSTGRES

DB KO
DBCNX

hostaddr=127.0.0.1 port=5432 dbname=postgres user=postgres password=password
QUIT
Connection closed by foreign host.

C’est l’échec, et c’est normal 🙁 … on essaye de se connecter en local, alors que le local c’est le conteneur !. Il faut donc se connecter à distance c’est à dire d’un conteneur à l’autre.

Je vais donc essayer d’utiliser la commande link :

[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
2fc533c55725        postgres            "/docker-entrypoint.s"   7 hours ago         Up 7 hours          0.0.0.0:5432->5432/tcp   postgres2
[root@localhost ~]# docker run -p 80:80 --link postgres2:postgres2 --name my-server2.2 -d my-server2
1c35469315b9de3d720ee963cfffe010a8efc069ee027c4e6c7bff119ea8865e
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
1c35469315b9        my-server2          "/sbin/server2"          18 seconds ago      Up 17 seconds       0.0.0.0:80->80/tcp       my-server2.2
2fc533c55725        postgres            "/docker-entrypoint.s"   7 hours ago         Up 7 hours          0.0.0.0:5432->5432/tcp   postgres2

Je regarde toutes les variables des deux containers afin de faire les modifications sur mon programme.

[root@localhost ~]# docker exec 2fc533c55725 env
PATH=/usr/lib/postgresql/9.5/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=2fc533c55725
POSTGRES_PASSWORD=password
GOSU_VERSION=1.7
LANG=en_US.utf8
PG_MAJOR=9.5
PG_VERSION=9.5.2-1.pgdg80+1
PGDATA=/var/lib/postgresql/data
HOME=/root
[root@localhost ~]# docker exec 1c35469315b9 env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=1c35469315b9
POSTGRES2_PORT=tcp://172.17.0.2:5432
POSTGRES2_PORT_5432_TCP=tcp://172.17.0.2:5432
POSTGRES2_PORT_5432_TCP_ADDR=172.17.0.2
POSTGRES2_PORT_5432_TCP_PORT=5432
POSTGRES2_PORT_5432_TCP_PROTO=tcp
POSTGRES2_NAME=/my-server2.2/postgres2
POSTGRES2_ENV_POSTGRES_PASSWORD=password
POSTGRES2_ENV_GOSU_VERSION=1.7
POSTGRES2_ENV_LANG=en_US.utf8
POSTGRES2_ENV_PG_MAJOR=9.5
POSTGRES2_ENV_PG_VERSION=9.5.2-1.pgdg80+1
POSTGRES2_ENV_PGDATA=/var/lib/postgresql/data
HOME=/root

On va faire notre server3.c, on a une seule ligne à modifier :

  /* Avant :
  conninfo =
    "hostaddr=127.0.0.1 port=5432 dbname=postgres user=postgres password=password";
     Après 
   */
   conninfo =
    "hostaddr=$POSTGRES2_PORT_5432_TCP_ADDR port=$POSTGRES2_PORT_5432_TCP_PORT user=postgres password=$POSTGRES2_ENV_POSTGRES_PASSWORD";

Ensuite modification du Dockerfile, puis build, … le résultat :

[root@localhost ~]# telnet 127.0.0.1 80
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.

HELLO
DB

hostaddr=$POSTGRES2_PORT_5432_TCP_ADDR port=$POSTGRES2_PORT_5432_TCP_PORT user=postgres password=$POSTGRES2_ENV_POSTGRES_PASSWORD
POSTGRES

DB KO
QUIT
Connection closed by foreign host.

Cela aurait été trop simple 😉 Donc on va utiliser un fonction pour faire cela, on va utiliser la fonction getenv. Les modifications dans server4.c

char conninfo[MAXDATASIZE];
...
  sprintf(conninfo,"hostaddr=%s port=%s user=postgres password=%s",getenv("POSTGRES2_PORT_5432_TCP_ADDR"), getenv("POSTGRES2_PORT_5432_TCP_PORT"), getenv("POSTGRES2_ENV_POSTGRES_PASSWORD"));

Je pourrais même faire mieux en faisant en sorte que cela marche en local et dans le container.

  printf("POSTGRES2_PORT_5432_TCP_ADDR : %s \n", getenv("POSTGRES2_PORT_5432_TCP_ADDR"));

  if(getenv("POSTGRES2_PORT_5432_TCP_ADDR") == NULL) {
  sprintf(conninfo,"hostaddr=%s port=%s user=postgres password=%s","127.0.0.1", "5432", "postgres");
 } else {
  sprintf(conninfo,"hostaddr=%s port=%s user=postgres password=%s",getenv("POSTGRES2_PORT_5432_TCP_ADDR"), getenv("POSTGRES2_PORT_5432_TCP_PORT"), getenv("POSTGRES2_ENV_POSTGRES_PASSWORD"));
  }

Le test … le stress en cas de nouvel échec 🙂 .

[root@localhost ~]# docker build -t my-server4 .
Sending build context to Docker daemon   129 kB
Step 1 : FROM fedora
 ---> ddd5c9c1d0f2
Step 2 : MAINTAINER toto toto@cyber-neurones.org
 ---> Using cache
 ---> bb6bc55cbbfc
Step 3 : COPY ./server4 /sbin/server4
 ---> 85cb6ab4dcea
Removing intermediate container 0f75d8dd2e32
Step 4 : RUN dnf install postgresql -y
 ---> Running in 3025055c6cfb
Last metadata expiration check performed 0:02:35 ago on Fri Apr 15 04:38:45 2016.
Dependencies resolved.
================================================================================
 Package                Arch          Version              Repository      Size
================================================================================
Installing:
 postgresql             x86_64        9.4.7-1.fc23         updates        1.1 M
 postgresql-libs        x86_64        9.4.7-1.fc23         updates        240 k

Transaction Summary
================================================================================
Install  2 Packages

Total download size: 1.3 M
Installed size: 4.4 M
Downloading Packages:
--------------------------------------------------------------------------------
Total                                           501 kB/s | 1.3 MB     00:02     
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Installing  : postgresql-libs-9.4.7-1.fc23.x86_64                         1/2 
  Installing  : postgresql-9.4.7-1.fc23.x86_64                              2/2 
  Verifying   : postgresql-9.4.7-1.fc23.x86_64                              1/2 
  Verifying   : postgresql-libs-9.4.7-1.fc23.x86_64                         2/2 

Installed:
  postgresql.x86_64 9.4.7-1.fc23       postgresql-libs.x86_64 9.4.7-1.fc23      

Complete!
 ---> 9541c83ce007
Removing intermediate container 3025055c6cfb
Step 5 : EXPOSE 80
 ---> Running in 1ae2a911c314
 ---> 944016c4027e
Removing intermediate container 1ae2a911c314
Step 6 : CMD /sbin/server4
 ---> Running in 7ca20a5578e2
 ---> 4f8c8c3fc2e5
Removing intermediate container 7ca20a5578e2
Successfully built 4f8c8c3fc2e5
[root@localhost ~]# docker run -p 80:80 --link postgres2:postgres2 --name my-server4.1 -d my-server4
08c524d398afb37c4568399d9d1f7325feb1954a4ac1593dc68684aa36b65e45
[root@localhost ~]# telnet 127.0.0.1 80
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.

HELLO
DBCNX

hostaddr=172.17.0.2 port=5432 user=postgres password=password
IP

eth0
INTERFACE

172.17.0.3
POSTGRES

DB OK
QUIT
Connection closed by foreign host.

J’ai donc mon programme qui fait bien ce que je veux, maintenant il va falloir passer à HAProxy. A force de repousser je vais finir par ne pas mettre les pieds dedans. La notion de lien (option -link) était importante à connaitre afin de pouvoir faire un dialogue entre containers.

Docker : le cinquième pas.

Attention ceci est mon brouillon avant de faire une belle documentation sur Docker (il y a à boire et à manger).

Avant de me lancer dans « HAProxy« , je vais faire un test avec « Docker Swarm« .

Pour l’instant « Docker Swarn » n’est pas un répartiteur de charge comme « HAproxy ». En fait il répartit la charge au moment du déploiement. Et aussi il permet le déploiement sur plusieurs servers à la fois, ce qui est un gain de temps énorme pour les administrateurs.

Je vais donc me lancer dans « Docker Swarm« , la première étape est la suivante :

[root@localhost ~]# docker pull swarm
Using default tag: latest
latest: Pulling from library/swarm
8c01723048ed: Pull complete 
28ef38ffcca5: Pull complete 
f1f933319091: Pull complete 
a3ed95caeb02: Pull complete 
Digest: sha256:8b007c8fc861cfaa2f0b9160e6ed3a39109af6e28dfe03982a05158e218bcc52
Status: Downloaded newer image for swarm:latest

On crée le swarm :

[root@localhost ~]# docker run --rm swarm create
553e1256993f92792ddd075713b16e34

Ensuite on lance des agents (bien noter le token en vert pour la suite):

[root@localhost ~]# docker run -d swarm join --advertise 10.0.0.101:2375 token://553e1256993f92792ddd075713b16e34
b61b2c9ea993e85279f720ebaa7bb60f1e187f2f09aa073772f7ae1ac99df636
[root@localhost ~]# docker run -d swarm join --advertise 10.0.0.102:2375 token://553e1256993f92792ddd075713b16e34
7acaca267109e1505890757a03d01b2833dd6dc2a750520bab46bf463d4c344b
[root@localhost ~]# docker run -d swarm join --advertise 10.0.0.103:2375 token://553e1256993f92792ddd075713b16e34
6c8fae76bce2c75be454944b3fd04a591f3811f6109e400dd62b0f9cab3a8c11
[root@localhost ~]# docker run -d swarm join --advertise 10.0.0.104:2375 token://553e1256993f92792ddd075713b16e34
75003c0fea9dfe0df1f613d360968758d96257aa27c19b39a671d4028235685f

J’ai donc 4 agents qui sont sur 4 ip différentes et qui écoutent sur le port 2375.
Maintenant je lance le manageur

[root@localhost ~]# docker run -d -p 80:2375 swarm manage token://553e1256993f92792ddd075713b16e34
cd4d60fd7638f775a4e04afad034877adf38a2b627abc31e4d4182ddd6e43470
docker: Error response from daemon: driver failed programming external connectivity on endpoint compassionate_mahavira (b4edffad195ad03292147ffe3cc6d753c6814c9b6bcd16835e01f249e64364e6): Bind for 0.0.0.0:80 failed: port is already allocated.

Aie cela plante car j’ai oublié de tuer le précédent qui écoute aussi sur le port 80.

[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
75003c0fea9d        swarm               "/swarm join --advert"   4 minutes ago       Up 4 minutes        2375/tcp                 nauseous_carson
6c8fae76bce2        swarm               "/swarm join --advert"   4 minutes ago       Up 4 minutes        2375/tcp                 adoring_visvesvaraya
7acaca267109        swarm               "/swarm join --advert"   4 minutes ago       Up 4 minutes        2375/tcp                 evil_northcutt
b61b2c9ea993        swarm               "/swarm join --advert"   4 minutes ago       Up 4 minutes        2375/tcp                 dreamy_lovelace
9cf698cacc2e        my-server           "/sbin/server"           About an hour ago   Up About an hour    0.0.0.0:80->80/tcp       my-server3
2fc533c55725        postgres            "/docker-entrypoint.s"   4 hours ago         Up 4 hours          0.0.0.0:5432->5432/tcp   postgres2
[root@localhost ~]# docker stop 9cf698cacc2e
9cf698cacc2e
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
75003c0fea9d        swarm               "/swarm join --advert"   5 minutes ago       Up 5 minutes        2375/tcp                 nauseous_carson
6c8fae76bce2        swarm               "/swarm join --advert"   5 minutes ago       Up 5 minutes        2375/tcp                 adoring_visvesvaraya
7acaca267109        swarm               "/swarm join --advert"   5 minutes ago       Up 5 minutes        2375/tcp                 evil_northcutt
b61b2c9ea993        swarm               "/swarm join --advert"   5 minutes ago       Up 5 minutes        2375/tcp                 dreamy_lovelace
2fc533c55725        postgres            "/docker-entrypoint.s"   4 hours ago         Up 4 hours          0.0.0.0:5432->5432/tcp   postgres2
[root@localhost ~]# docker run -d -p 80:2375 swarm manage token://553e1256993f92792ddd075713b16e34
37a3a8a409b6683c7495cbbda3f18f7e1bd2da3c364252303ba52860eaba9a64
[root@localhost ~]# docker run --rm swarm list token://553e1256993f92792ddd075713b16e34
10.0.0.104:2375
10.0.0.102:2375
10.0.0.103:2375
10.0.0.101:2375
[root@localhost ~]# telnet 127.0.0.1 80
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.

HTTP/1.1 400 Bad Request

Maintenant je peux donc repasser à HAproxy qui est un vrai loadbalanceur. Pour le loadbalanceur il y a aussi Nginx.

Les notions à connaitre sous Docker semblent être (dans un premier temps):

  • Consul pour la découverte des services de façon dynamique.
  • Nginx ou HAProxy pour la répartition de charge.
  • Registrator pour s’enregistrer en temps que service.
  • La création d’un Dockerfile
  • Le lancement, l’arrêt, le status de ./Container sous Docker.

Je vais essayer de faire une documentation détaillée quand je maitriserais un peu mieux.

Docker : le quatrième pas.

Attention ceci est mon brouillon avant de faire une belle documentation sur Docker (il y a à boire et à manger). 

Je commence donc par faire table rase de toutes les images, a force de jouer je ne sais plus ou j’en suis 😉

[root@localhost ~]# docker rmi $(docker images -q)
[root@localhost ~]# docker rm $(docker ps -a -q)
Error response from daemon: conflict: unable to delete 0f3af79d8673 (cannot be forced) - image is being used by running container f33064cbf168
[root@localhost ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
postgres            latest              0f3af79d8673        9 days ago          265.7 MB

Visiblement ils (les containers) n’étaient pas tous arrêtés .

[root@localhost ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
postgres            latest              0f3af79d8673        9 days ago          265.7 MB
[root@localhost ~]# docker stop $( docker ps -a -q)
f33064cbf168
[root@localhost ~]# docker rm $(docker ps -a -q)
f33064cbf168
[root@localhost ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
postgres            latest              0f3af79d8673        9 days ago          265.7 MB

Maintenant je fais « mon installation » classique de PostgreSQL dans le Dockfile.

[root@localhost ~]# cat Dockerfile
FROM fedora
MAINTAINER toto toto@cyber-neurones.org 
RUN dnf install postgresql -y 
RUN dnf install postgresql-server postgresql-contrib -y 
# Modification de la configuration 
#RUN echo "host all all 0.0.0.0/0 md5" >> /var/lib/pgsql/data/pg_hba.conf 
RUN echo "local 		all		all 			trust" > /var/lib/pgsql/data/pg_hba.conf
RUN echo "host 		all 		all 	127.0.0.1/32 	trust" >> /var/lib/pgsql/data/pg_hba.conf
RUN echo "host 		all 		all 	::1/128 	trust" >> /var/lib/pgsql/data/pg_hba.conf

#RUN echo "listen_addresses='*'" >> /var/lib/pgsql/data/postgresql.conf 
#RUN echo "tcpip_socket = true" >> /var/lib/pgsql/data/postgresql.conf 

RUN echo "tcpip_socket = true          #" > /var/lib/pgsql/data/postgresql.conf
RUN echo "max_connections = 124        #" >> /var/lib/pgsql/data/postgresql.conf
RUN echo "sort_mem = 2048              #" >> /var/lib/pgsql/data/postgresql.conf
RUN echo "shared_buffers = 1024        #" >> /var/lib/pgsql/data/postgresql.conf
RUN echo "debug_level = 0              #" >> /var/lib/pgsql/data/postgresql.conf
RUN echo "debug_print_query = false     #" >> /var/lib/pgsql/data/postgresql.conf
RUN echo "debug_print_parse = false     #" >> /var/lib/pgsql/data/postgresql.conf
RUN echo "debug_print_rewritten = false #" >> /var/lib/pgsql/data/postgresql.conf
RUN echo "debug_print_plan = false      #" >> /var/lib/pgsql/data/postgresql.conf
RUN echo "debug_pretty_print = false    #" >> /var/lib/pgsql/data/postgresql.conf

USER postgres
ENV PGDATA /var/lib/pgsql/data
#Comment lancer PostgreSQL pour créer les utilisateurs ?
#RUN /etc/init.d/postgresql start ...
#RUN /etc/rc.d/init.d/postgresql start ...
#RUN service postgres start ...
RUN systemctl start postgres.service &&\ psql --command "CREATE USER docker WITH SUPERUSER PASSWORD 'docker';" &&\ createdb -O docker docker 
#RUN initdb --data-checksums 
# Le port en ecoute 
EXPOSE 5432 
# Ajout des volumes pour faire un backup 
VOLUME ["/etc/postgresql", "/var/log/postgresql", "/var/lib/pgsql"] 
# Pour lancer postgres 
CMD ["/var/lib/pgsql/bin/postgres", "-D", "/var/lib/pgsql/data", "-c", "config_file=/var/lib/pgsql/data/postgresql.conf"]

Quand je lance la création :

[root@localhost ~]# docker build -t my-postgres .
Sending build context to Docker daemon 17.41 kB
...
Step 20 : RUN systemctl start postgres.service &&    psql --command "CREATE USER docker WITH SUPERUSER PASSWORD 'docker';" &&    createdb -O docker docker
 ---> Running in c2b02a1f1bca
Failed to get D-Bus connection: Operation not permitted
The command '/bin/sh -c systemctl start postgres.service &&    psql --command "CREATE USER docker WITH SUPERUSER PASSWORD 'docker';" &&    createdb -O docker docker' returned a non-zero code: 1

ou alors cette erreur :

[root@localhost ~]# docker build -t my-postgres .
Sending build context to Docker daemon 17.41 kB
...
Step 20 : RUN /etc/init.d/postgresql start &&    psql --command "CREATE USER docker WITH SUPERUSER PASSWORD 'docker';" &&    createdb -O docker docker
 ---> Running in 4dfdeb08e3f3
/bin/sh: /etc/init.d/postgresql: No such file or directory
The command '/bin/sh -c /etc/init.d/postgresql start &&    psql --command "CREATE USER docker WITH SUPERUSER PASSWORD 'docker';" &&    createdb -O docker docker' returned a non-zero code: 127

ou encore :

[root@localhost ~]# docker build -t my-postgres .
Sending build context to Docker daemon 17.41 kB
...
Step 20 : RUN service postgres start &&    psql --command "CREATE USER docker WITH SUPERUSER PASSWORD 'docker';" &&    createdb -O docker docker
 ---> Running in 9a3bfd9a664f
/bin/sh: service: command not found
The command '/bin/sh -c service postgres start &&    psql --command "CREATE USER docker WITH SUPERUSER PASSWORD 'docker';" &&    createdb -O docker docker' returned a non-zero code: 127

Je laisse donc tomber provisoirement l’ajout d’un utilisateur Docker et la création de la db Docker dans le Dockerfile 🙁 .

[root@localhost ~]# docker build -t my-postgres .
Sending build context to Docker daemon 17.92 kB
Step 1 : FROM fedora
 ---> ddd5c9c1d0f2
Step 2 : MAINTAINER toto toto@cyber-neurones.org
 ---> Using cache
 ---> bb6bc55cbbfc
Step 3 : RUN dnf install postgresql -y
 ---> Using cache
 ---> 9b581b9c8425
Step 4 : RUN dnf install postgresql-server postgresql-contrib -y
 ---> Using cache
 ---> ed6bccd45fd3
Step 5 : RUN echo "local 		all		all 			trust" > /var/lib/pgsql/data/pg_hba.conf
 ---> Using cache
 ---> 8a3ea8273f9e
Step 6 : RUN echo "host 		all 		all 	127.0.0.1/32 	trust" >> /var/lib/pgsql/data/pg_hba.conf
 ---> Using cache
 ---> fc65b9c9661e
Step 7 : RUN echo "host 		all 		all 	::1/128 	trust" >> /var/lib/pgsql/data/pg_hba.conf
 ---> Using cache
 ---> 6c9ab1b370d6
Step 8 : RUN echo "tcpip_socket = true          #" > /var/lib/pgsql/data/postgresql.conf
 ---> Using cache
 ---> ac205ea5bbf7
Step 9 : RUN echo "max_connections = 124        #" >> /var/lib/pgsql/data/postgresql.conf
 ---> Using cache
 ---> 975e0845fdbb
Step 10 : RUN echo "sort_mem = 2048              #" >> /var/lib/pgsql/data/postgresql.conf
 ---> Using cache
 ---> 23ab63545319
Step 11 : RUN echo "shared_buffers = 1024        #" >> /var/lib/pgsql/data/postgresql.conf
 ---> Using cache
 ---> 327533e655c4
Step 12 : RUN echo "debug_level = 0              #" >> /var/lib/pgsql/data/postgresql.conf
 ---> Using cache
 ---> 7e51ec7dd6cb
Step 13 : RUN echo "debug_print_query = false     #" >> /var/lib/pgsql/data/postgresql.conf
 ---> Using cache
 ---> 0b8663d1fe21
Step 14 : RUN echo "debug_print_parse = false     #" >> /var/lib/pgsql/data/postgresql.conf
 ---> Using cache
 ---> 82879441164c
Step 15 : RUN echo "debug_print_rewritten = false #" >> /var/lib/pgsql/data/postgresql.conf
 ---> Using cache
 ---> 3bd7eb375391
Step 16 : RUN echo "debug_print_plan = false      #" >> /var/lib/pgsql/data/postgresql.conf
 ---> Using cache
 ---> b269cdf8abf3
Step 17 : RUN echo "debug_pretty_print = false    #" >> /var/lib/pgsql/data/postgresql.conf
 ---> Using cache
 ---> 8bad41390294
Step 18 : RUN echo "listen_addresses='*'          #" >> /var/lib/pgsql/data/postgresql.conf
 ---> Running in f53205205b0b
 ---> 896e6064081e
Removing intermediate container f53205205b0b
Step 19 : USER postgres
 ---> Running in 3d4aa9d10075
 ---> 77f821b4582f
Removing intermediate container 3d4aa9d10075
Step 20 : ENV PGDATA /var/lib/pgsql/data
 ---> Running in 1d25c9d8ee02
 ---> 86584da17774
Removing intermediate container 1d25c9d8ee02
Step 21 : EXPOSE 5432
 ---> Running in 0c2d98c939de
 ---> 60baae86afc9
Removing intermediate container 0c2d98c939de
Step 22 : VOLUME /etc/postgresql /var/log/postgresql /var/lib/pgsql
 ---> Running in d6f248e4b0f6
 ---> 3a00e74a6f0f
Removing intermediate container d6f248e4b0f6
Step 23 : CMD /var/lib/pgsql/bin/postgres -D /var/lib/pgsql/data -c config_file=/var/lib/pgsql/data/postgresql.conf
 ---> Running in 46016d0af473
 ---> 4b31f92a3ed5
Removing intermediate container 46016d0af473
Successfully built 4b31f92a3ed5
[root@localhost ~]# docker run -p 5432:5432 --name postgres2 -e POSTGRES_PASSWORD=password -d postgres
2fc533c557259f65236a97e1e4eb7123867d4c0e0cae784a620cc9c96e55c168
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
2fc533c55725        postgres            "/docker-entrypoint.s"   24 seconds ago      Up 24 seconds       0.0.0.0:5432->5432/tcp   postgres2
[root@localhost ~]# psql -h localhost -p 5432 -u postgres
psql : option invalide -- 'u'
Essayez « psql --help » pour plus d'informations.
[root@localhost ~]# psql -h localhost -p 5432 -d postgres
Mot de passe : 
psql: FATAL:  password authentication failed for user "root"

[root@localhost ~]# adduser postgres
[root@localhost ~]# su postgres
[postgres@localhost root]$ cd
[postgres@localhost ~]$ psql -h localhost -p 5432 -d postgres
Mot de passe : 
psql (9.2.15, serveur 9.5.2)
ATTENTION : psql version 9.2, version du serveur 9.5.
         Certaines fonctionnalités de psql pourraient ne pas fonctionner.
Saisissez « help » pour l'aide.

postgres=# 

J’ai donc ajouter l’utilisateur postgres en local afin d’avoir l’accès à PostgreSQL. J’aurai pu aussi utiliser l’option -U pour préciser l’utilisateur à psql.

[postgres@localhost ~]$ psql -h localhost -p 5432 -d postgres -U postgres
Mot de passe pour l'utilisateur postgres : 
psql (9.2.15, serveur 9.5.2)
ATTENTION : psql version 9.2, version du serveur 9.5.
         Certaines fonctionnalités de psql pourraient ne pas fonctionner.
Saisissez « help » pour l'aide.

postgres=# create database Docker;
CREATE DATABASE
postgres=# CREATE USER Docker WITH PASSWORD 'Docker';
CREATE ROLE
postgres=# GRANT ALL PRIVILEGES ON DATABASE Docker to Docker;
GRANT

Maintenant on va développer un serveur pour voir s’il est possible de lancer des containers dynamiquement. On va limiter ce server à 5 clients maximums et on va essayer de lancer un nouveau conteneur quand les 5 clients seront occupés.

Le source de server.c:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h> 
#include <sys/types.h> 
#include <netinet/in.h> 
#include <sys/socket.h> 
#include <sys/wait.h> 
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/un.h> 

#define MYPORT 80  
#define BACKLOG 5   
#define MAXCLIENTS 5
#define MAXDATASIZE 100

int main(void)
{
   int sockfd = -1,new_fd,numbytes,highest = 0,i;
   int clients[MAXCLIENTS];
   char buffer[MAXDATASIZE] ;

   struct sockaddr_in my_addr,their_addr;
   socklen_t sin_size;
   struct timeval tv;
   fd_set readfds;

   if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
     perror("SOCKET");
     exit(-1);
   }
   my_addr.sin_family = AF_INET;        
   my_addr.sin_port = htons(MYPORT);   
   my_addr.sin_addr.s_addr = INADDR_ANY; 
   bzero(&(my_addr.sin_zero), 8);

   if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
      perror("BIND");
      exit(-1);
   }
   if (listen(sockfd, BACKLOG) == -1) {
      perror("LISTEN");
      exit(-1);
   }
   bzero(clients,sizeof(clients));
   highest = sockfd ;
   while(1) {
      sin_size = sizeof(struct sockaddr_in);      
      tv.tv_sec = 0;
      tv.tv_usec = 250000;
      FD_ZERO(&readfds);
      for ( i = 0 ; i < MAXCLIENTS ; i ++ ) { if ( clients[i] != 0 ) { FD_SET(clients[i],&readfds); } } FD_SET(sockfd,&readfds); if (select(highest+1, &readfds, NULL, NULL, &tv) >=0 ) {
         if (FD_ISSET(sockfd, &readfds)) {
            if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) {
               perror("ACCEPT");
               continue;
            } 
            for( i = 0 ; i < MAXCLIENTS ; i ++ ) { if ( clients[i] == 0 ) { clients[i] = new_fd ; break; } } if ( i != MAXCLIENTS ) { if ( new_fd > highest ) {
                  highest = clients[i] ;
               }
               printf("Connexion received from %s (slot %i) ",inet_ntoa(their_addr.sin_addr),i);
               send(new_fd,"PING",4,MSG_NOSIGNAL);
            }     
            else {
               send(new_fd, "TOO MANY CLIENT",15,MSG_NOSIGNAL); 
               close(new_fd);   
            }
         }
         for ( i = 0 ; i < MAXCLIENTS ; i ++ ) {
            if ( FD_ISSET(clients[i],&readfds) ) {
               if ( (numbytes=recv(clients[i],buffer,MAXDATASIZE,0)) <= 0 ) {
                  printf("Connexion lost from slot %i",i);  
                  close(clients[i]);
                  clients[i] = 0 ;
               }
               else {
                  buffer[numbytes] = '\0';
                  printf("Received from slot %i : %s",i,buffer); 
               }
            }
         }
      } 
      else {
         perror("select");
         continue;
      }
   }
   return 0;
}

On compile :

[root@localhost ~]# yum install gcc
...
[root@localhost ~]# gcc -o server server.c

On lance et on fait un petit test :

[root@localhost ~]# telnet 127.0.0.1 80
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.

PING

Attention il faut deux shell pour faire le test du telnet, un qui lance le ./server et l’autre qui fait le telnet.

Maintenant on va essayer de faire un conteneur de cette superbe application 😉 On va faire cela sur une base de Fédora.

[root@localhost ~]# docker build -t my-server .
Sending build context to Docker daemon 37.38 kB
Step 1 : FROM fedora
 ---> ddd5c9c1d0f2
Step 2 : MAINTAINER toto toto@cyber-neurones.org
 ---> Using cache
 ---> bb6bc55cbbfc
Step 3 : COPY ./server /sbin/server
 ---> 47dae6f4617a
Removing intermediate container adc5565dac13
Step 4 : EXPOSE 80
 ---> Running in 16c1c17c481b
 ---> 80328c54f6b4
Removing intermediate container 16c1c17c481b
Step 5 : CMD /sbin/server
 ---> Running in 621a41123e73
 ---> fea70bdfa97c
Removing intermediate container 621a41123e73
Successfully built fea70bdfa97c
[root@localhost ~]# cat Dockerfile
FROM fedora
MAINTAINER toto toto@cyber-neurones.org 
COPY ./server /sbin/server
# Le port en ecoute 
EXPOSE 80 
# Pour lancer postgres 
CMD ["/sbin/server"]

Ensuite on lance le container, et si j’essaye de lancer sur ce même port on voit qu’il y a une erreur :

[root@localhost ~]# docker run -p 80:80 --name my-server3 -d my-server 
9cf698cacc2e1e43d67c83b1b4c72e17f190559722e90517dca6095e9513a426
[root@localhost ~]# docker run -p 80:80 --name my-server4 -d my-server 
d40fe77df35aad7cec0e35d934a1dd73395eba40727f5367a529429c21264741
docker: Error response from daemon: driver failed programming external connectivity on endpoint my-server4 (11fe895fc0c58deab22b2cde63fb1f72cd58b1c21178a114897a699ec2e9e627): Bind for 0.0.0.0:80 failed: port is already allocated.

[root@localhost ~]# telnet 127.0.0.1 80
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.

PING

La prochaine étape serait de mettre HAproxy devant mon server sur le port 80. Pour ensuite faire du balancing sur plusieurs de mes servers.

Capture d’écran 2016-04-19 à 08.01.48

Docker : Le troisième pas .

Attention ceci est mon brouillon avant de faire une belle documentation sur Docker (il y a à boire et à manger). 

Maintenant on a mieux compris le système (enfin j’ai mieux compris) et l’on sait qu’il faut faire les choses dans une certain ordre (Les précédents POST n°1 et n°2 ) .

  • On a compris qu’il fallait une partition spéciale (par exemple Btrfs) pour Docker.
  • On a compris qu’il devait y avoir une version « spéciale » pour Docker sous Oracle Linux. Mais on a préféré prendre la version standard. Par exemple on doit avoir le fichier /etc/sysconfig/docker .
  • On a compris qu’il fallait avant tout faire le fichier Dockerfile
    , puis le « docker build » et « docker run« .
  • On a aussi l’option -v qui permet de faire le lien entre l’hôte et le container.
  • On a pris le risque de mettre le dernier noyau  4.1.12-32.2.3.el7uek.x86_64 , afin d’avoir la dernière version de Docker. Ce n’est jamais bon d’être sur les derniers version car on est le premier a se prendre les nouveaux problèmes.

Maintenant on va pouvoir lancer des containers en utilisant la syntaxe :

docker run -p <hôte_port1>:<container_port1> -p <hôte_port2>:<container_port2> …

Car jusqu’à présent on n’a pas vu de port en écoute, c’est parce que l’on n’a pas fait le lien entre le port hôte et le port du conteneur.

Plutôt que de continuer avec HAproxy on va faire avoir PostgreSQL qui me semble plus simple à mettre en oeuvre dans un premier temps.

Je redonne les informations de mon docker :

[root@localhost ~]# docker info
Containers: 1
 Running: 0
 Paused: 0
 Stopped: 1
Images: 4
Server Version: 1.11.0
Storage Driver: btrfs
 Build Version: Btrfs v3.19.1
 Library Version: 101
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins: 
 Volume: local
 Network: bridge null host
Kernel Version: 4.1.12-32.2.3.el7uek.x86_64
Operating System: Oracle Linux Server 7.2
OSType: linux
Architecture: x86_64
CPUs: 1
Total Memory: 739.1 MiB
Name: localhost.localdomain
ID: X7PA:FHLQ:XKJJ:IH72:P5HO:ULDH:ZMID:VGSB:KOMV:AJGF:SEY6:PTGV
Docker Root Dir: /docker
Debug mode (client): false
Debug mode (server): false
Registry: https://index.docker.io/v1/

On se lance donc dans PostgreSQL, d’abord on regarde ce qui est disponible :

[root@localhost ~]# docker search postgres
NAME                         DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
postgres                     The PostgreSQL object-relational database ...   1909      [OK]       
abevoelker/postgres          Postgres 9.3 + WAL-E + PL/V8 and PL/Python...   10                   [OK]
macadmins/postgres           Postgres that accepts remote connections b...   8                    [OK]
jamesbrink/postgres          Highly configurable PostgreSQL container.       5                    [OK]
linuxkonsult/postgres        A Postgres trusted build installed with Chef.   5                    [OK]
cptactionhank/postgres                                                       4                    [OK]
kampka/postgres              A postgresql image build on top of an arch...   2                    [OK]
azukiapp/postgres            Docker image to run PostgreSQL by Azuki - ...   2                    [OK]
eeacms/postgres              Docker image for PostgreSQL (RelStorage re...   2                    [OK]
icescrum/postgres            PostgreSQL image for iceScrum.                  1                    [OK]
clkao/postgres-plv8          Docker image for running PLV8 1.4 on Postg...   1                    [OK]
jgiannuzzi/postgres-bdr      Docker image for PostgreSQL with BDR support    1                    [OK]
baselibrary/postgres         ThoughtWorks Postgres & PostGIS Docker Image    1                    [OK]
travix/postgres              A container to run the PostgreSQL database.     0                    [OK]
timbira/postgres             Postgres  containers                            0                    [OK]
blacklabelops/postgres       Postgres Image for Atlassian Applications       0                    [OK]
livingdocs/postgres          Postgres v9.3 with the plv8 extension inst...   0                    [OK]
opencog/postgres             This is a configured postgres database for...   0                    [OK]
beorc/postgres               Ubuntu-based PostgreSQL server                  0                    [OK]
vrtsystems/postgres          PostgreSQL image with added init hooks, bu...   0                    [OK]
vibioh/postgres              PostgresQL Server                               0                    [OK]
coreroller/postgres          official postgres:9.4 image but it adds 2 ...   0                    [OK]
khipu/postgres               postgres with custom uids                       0                    [OK]
aheimsbakk/postgres-nosync   `postgres` docker with `synchronous_commit...   0                    [OK]
akilli/postgres              debian:jessie based PostgreSQL image            0                    [OK]

Maintenant je regarde quel est la dernière version de PostgreSQL :

FROM postgres:latest 
MAINTAINER toto toto@cyber-neurones.org 
RUN yum install postgresql && yum install postgresql-server 
RUN /etc/init.d/postgresql initdb 
# Modification de la configuration 
RUN echo "host all all 0.0.0.0/0 md5" >> /var/lib/pgsql/data/pg_hba.conf 
RUN echo "listen_addresses='*'" >> /var/lib/pgsql/data/postgresql.conf 
# Le port en ecoute 
EXPOSE 5432 
# Ajout des volumes pour faire un backup 
VOLUME ["/etc/postgresql", "/var/log/postgresql", "/var/lib/pgsql"] 
# Pour lancer postgres 
CMD ["/var/lib/pgsql/bin/postgres", "-D", "/var/lib/pgsql/data", "-c", "config_file=/var/lib/pgsql/data/postgresql.conf"]

Je me lance donc dans le test de mon premier fichier ! La première étape c’est le build :

[root@localhost ~]# docker build -t my-postgres .
Sending build context to Docker daemon 15.36 kB
Step 1 : FROM postgres:latest
latest: Pulling from library/postgres
efd26ecc9548: Already exists 
a3ed95caeb02: Pull complete 
aef28b128f84: Pull complete 
5c6681af0d52: Pull complete 
43fd2592d569: Pull complete 
90b140d542bd: Pull complete 
9f56303d7da8: Pull complete 
75f16d91384c: Pull complete 
a7e55988e47e: Pull complete 
6980fe8c2745: Pull complete 
94512148bc3a: Pull complete 
055e85b433f4: Pull complete 
Digest: sha256:3ab14aa8758e62570f589848a93039a55c9e3ab123090c58721374d4f633ff71
Status: Downloaded newer image for postgres:latest
 ---> 0f3af79d8673
Step 2 : MAINTAINER toto toto@cyber-neurones.org
 ---> Running in 4ee6e08a7c8c
 ---> dadadc713dfa
Removing intermediate container 4ee6e08a7c8c
Step 3 : RUN yum install postgresql && yum install postgresql-server RUN /etc/init.d/postgresql initdb
 ---> Running in 5cfa35a21346
/bin/sh: 1: yum: not found
The command '/bin/sh -c yum install postgresql && yum install postgresql-server RUN /etc/init.d/postgresql initdb' returned a non-zero code: 127

Aie le yum ne passe pas … j’ai ajouté l’option -y mais pas mieux (l’option -y permet de répondre y aux questions, c’est impératif en ligne de commande).

RUN yum install postgresql -y && yum install postgresql-server -y RUN /etc/init.d/postgresql initdb

La commande yum n’est pas dispo, on est donc sur une base Débian. On va donc faire un apt-get ! ou alors on va partir d’une base de Fédora (proche de Oracle Linux) pour avoir la commande yum.

Voici donc mon nouveau fichier :

FROM fedora
MAINTAINER toto toto@cyber-neurones.org
RUN yum install postgresql -y 
RUN yum install postgresql-server -y
RUN /etc/init.d/postgresql initdb
# Modification de la configuration
RUN echo "host all all 0.0.0.0/0 md5" >> /var/lib/pgsql/data/pg_hba.conf
RUN echo "listen_addresses='*'" >> /var/lib/pgsql/data/postgresql.conf
# Le port en ecoute
EXPOSE 5432
# Ajout des volumes pour faire un backup
VOLUME ["/etc/postgresql", "/var/log/postgresql", "/var/lib/pgsql"]
# Pour lancer postgres
CMD ["/var/lib/pgsql/bin/postgres", "-D", "/var/lib/pgsql/data", "-c", "config_file=/var/lib/pgsql/data/postgresql.conf"]

On refait un test :

[root@localhost ~]# docker build -t my-postgres .
Sending build context to Docker daemon 15.36 kB
Step 1 : FROM fedora
 ---> ddd5c9c1d0f2
Step 2 : MAINTAINER toto toto@cyber-neurones.org
 ---> Using cache
 ---> f170274e277c
Step 3 : RUN yum install postgresql -y
 ---> Running in a8bd83110986
Yum command has been deprecated, redirecting to '/usr/bin/dnf install postgresql -y'.
See 'man dnf' and 'man yum2dnf' for more information.
To transfer transaction metadata from yum to DNF, run:
'dnf install python-dnf-plugins-extras-migrate && dnf-2 migrate'

Last metadata expiration check performed 0:00:47 ago on Thu Apr 14 17:50:24 2016.
Dependencies resolved.
================================================================================
 Package                Arch          Version              Repository      Size
================================================================================
Installing:
 postgresql             x86_64        9.4.7-1.fc23         updates        1.1 M
 postgresql-libs        x86_64        9.4.7-1.fc23         updates        240 k

Transaction Summary
================================================================================
Install  2 Packages

Total download size: 1.3 M
Installed size: 4.4 M
Downloading Packages:
--------------------------------------------------------------------------------
Total                                            75 kB/s | 1.3 MB     00:18     
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Installing  : postgresql-libs-9.4.7-1.fc23.x86_64                         1/2 
  Installing  : postgresql-9.4.7-1.fc23.x86_64                              2/2 
  Verifying   : postgresql-9.4.7-1.fc23.x86_64                              1/2 
  Verifying   : postgresql-libs-9.4.7-1.fc23.x86_64                         2/2 

Installed:
  postgresql.x86_64 9.4.7-1.fc23       postgresql-libs.x86_64 9.4.7-1.fc23      

Complete!
 ---> 398c5e8555cb
Removing intermediate container a8bd83110986
Step 4 : RUN yum install postgresql-server -y
 ---> Running in 1dc2f23f63bd
Yum command has been deprecated, redirecting to '/usr/bin/dnf install postgresql-server -y'.
See 'man dnf' and 'man yum2dnf' for more information.
To transfer transaction metadata from yum to DNF, run:
'dnf install python-dnf-plugins-extras-migrate && dnf-2 migrate'

Last metadata expiration check performed 0:01:15 ago on Thu Apr 14 17:50:24 2016.
Dependencies resolved.
================================================================================
 Package                 Arch         Version               Repository     Size
================================================================================
Installing:
 postgresql-server       x86_64       9.4.7-1.fc23          updates       4.0 M

Transaction Summary
================================================================================
Install  1 Package

Total download size: 4.0 M
Installed size: 17 M
Downloading Packages:
--------------------------------------------------------------------------------
Total                                           585 kB/s | 4.0 MB     00:07     
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Installing  : postgresql-server-9.4.7-1.fc23.x86_64                       1/1 
  Verifying   : postgresql-server-9.4.7-1.fc23.x86_64                       1/1 

Installed:
  postgresql-server.x86_64 9.4.7-1.fc23                                         

Complete!
 ---> 7592731d113b
Removing intermediate container 1dc2f23f63bd
Step 5 : RUN /etc/init.d/postgresql initdb
 ---> Running in 29aa04f7d09a
/bin/sh: /etc/init.d/postgresql: No such file or directory
The command '/bin/sh -c /etc/init.d/postgresql initdb' returned a non-zero code: 127

Encore un échec, mais je ne baisse pas les bras 😉 Voici ma version n°3 du fichier :

FROM fedora
MAINTAINER toto toto@cyber-neurones.org 
RUN dnf install postgresql -y 
RUN dnf install postgresql-server -y 
RUN postgresql-setup initdb 
# Modification de la configuration 
RUN echo "host all all 0.0.0.0/0 md5" >> /var/lib/pgsql/data/pg_hba.conf 
RUN echo "listen_addresses='*'" >> /var/lib/pgsql/data/postgresql.conf 
# Le port en ecoute 
EXPOSE 5432 
# Ajout des volumes pour faire un backup 
VOLUME ["/etc/postgresql", "/var/log/postgresql", "/var/lib/pgsql"] 
# Pour lancer postgres 
CMD ["/var/lib/pgsql/bin/postgres", "-D", "/var/lib/pgsql/data", "-c", "config_file=/var/lib/pgsql/data/postgresql.conf"]

Maintenant le test :

[root@localhost ~]# docker build -t my-postgres .
Sending build context to Docker daemon 15.36 kB
Step 1 : FROM fedora
 ---> ddd5c9c1d0f2
Step 2 : MAINTAINER toto toto@cyber-neurones.org
 ---> Using cache
 ---> f170274e277c
Step 3 : RUN dnf install postgresql -y
 ---> Running in 3cbd03b57500
Last metadata expiration check performed 0:00:43 ago on Thu Apr 14 17:57:13 2016.
Dependencies resolved.
================================================================================
 Package                Arch          Version              Repository      Size
================================================================================
Installing:
 postgresql             x86_64        9.4.7-1.fc23         updates        1.1 M
 postgresql-libs        x86_64        9.4.7-1.fc23         updates        240 k

Transaction Summary
================================================================================
Install  2 Packages

Total download size: 1.3 M
Installed size: 4.4 M
Downloading Packages:
--------------------------------------------------------------------------------
Total                                            75 kB/s | 1.3 MB     00:18     
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Installing  : postgresql-libs-9.4.7-1.fc23.x86_64                         1/2 
  Installing  : postgresql-9.4.7-1.fc23.x86_64                              2/2 
  Verifying   : postgresql-9.4.7-1.fc23.x86_64                              1/2 
  Verifying   : postgresql-libs-9.4.7-1.fc23.x86_64                         2/2 

Installed:
  postgresql.x86_64 9.4.7-1.fc23       postgresql-libs.x86_64 9.4.7-1.fc23      

Complete!
 ---> 3d2c98e008bc
Removing intermediate container 3cbd03b57500
Step 4 : RUN dnf install postgresql-server -y
 ---> Running in ea14d4661833
Last metadata expiration check performed 0:01:10 ago on Thu Apr 14 17:57:13 2016.
Dependencies resolved.
================================================================================
 Package                 Arch         Version               Repository     Size
================================================================================
Installing:
 postgresql-server       x86_64       9.4.7-1.fc23          updates       4.0 M

Transaction Summary
================================================================================
Install  1 Package

Total download size: 4.0 M
Installed size: 17 M
Downloading Packages:
--------------------------------------------------------------------------------
Total                                           488 kB/s | 4.0 MB     00:08     
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Installing  : postgresql-server-9.4.7-1.fc23.x86_64                       1/1 
  Verifying   : postgresql-server-9.4.7-1.fc23.x86_64                       1/1 

Installed:
  postgresql-server.x86_64 9.4.7-1.fc23                                         

Complete!
 ---> 7dde38450b15
Removing intermediate container ea14d4661833
Step 5 : RUN postgresql-setup initdb
 ---> Running in 1fa62834212e
WARNING: using obsoleted argument syntax, try --help
WARNING: arguments transformed to: postgresql-setup --initdb --unit postgresql
/usr/share/postgresql-setup/library.sh: line 63: find: command not found
Failed to get D-Bus connection: Operation not permitted
Failed to get D-Bus connection: Operation not permitted
FATAL: no db datadir (PGDATA) configured for 'postgresql.service' unit
The command '/bin/sh -c postgresql-setup initdb' returned a non-zero code: 1

On va dire que l’on a encore avancé mais pas facile de trouver de la documentation claire pour l’instant. En plus du yum qui a changé en dnf, la commande l’initialisation de postgres n’est plus la même. La compatibilité ascendante c’est pour demain 😉

[root@localhost ~]# cat Dockerfile
FROM fedora
MAINTAINER toto toto@cyber-neurones.org 
RUN dnf install postgresql -y 
RUN dnf install postgresql-server -y 
RUN postgresql-setup --initdb --unit postgresql
# Modification de la configuration 
RUN echo "host all all 0.0.0.0/0 md5" >> /var/lib/pgsql/data/pg_hba.conf 
RUN echo "listen_addresses='*'" >> /var/lib/pgsql/data/postgresql.conf 
# Le port en ecoute 
EXPOSE 5432 
# Ajout des volumes pour faire un backup 
VOLUME ["/etc/postgresql", "/var/log/postgresql", "/var/lib/pgsql"] 
# Pour lancer postgres 
CMD ["/var/lib/pgsql/bin/postgres", "-D", "/var/lib/pgsql/data", "-c", "config_file=/var/lib/pgsql/data/postgresql.conf"]

[root@localhost ~]# docker build -t my-postgres .
Sending build context to Docker daemon 15.36 kB
Step 1 : FROM fedora
 ---> ddd5c9c1d0f2
Step 2 : MAINTAINER toto toto@cyber-neurones.org
 ---> Using cache
 ---> f170274e277c
Step 3 : RUN dnf install postgresql -y
 ---> Using cache
 ---> 3d2c98e008bc
Step 4 : RUN dnf install postgresql-server -y
 ---> Using cache
 ---> 7dde38450b15
Step 5 : RUN postgresql-setup --initdb --unit postgresql
 ---> Running in b4dd8e2cef49
/usr/share/postgresql-setup/library.sh: line 63: find: command not found
Failed to get D-Bus connection: Operation not permitted
Failed to get D-Bus connection: Operation not permitted
FATAL: no db datadir (PGDATA) configured for 'postgresql.service' unit
The command '/bin/sh -c postgresql-setup --initdb --unit postgresql' returned a non-zero code: 1

Je ne vais pas faire d’initdb …

[root@localhost ~]# docker build -t my-postgres .
Sending build context to Docker daemon 15.36 kB
Step 1 : FROM fedora
 ---> ddd5c9c1d0f2
Step 2 : MAINTAINER toto toto@cyber-neurones.org
 ---> Using cache
 ---> f170274e277c
Step 3 : RUN dnf install postgresql -y
 ---> Using cache
 ---> 3d2c98e008bc
Step 4 : RUN dnf install postgresql-server postgresql-contrib -y
 ---> Using cache
 ---> 29c873629d39
Step 5 : RUN echo "host all all 0.0.0.0/0 md5" >> /var/lib/pgsql/data/pg_hba.conf
 ---> Using cache
 ---> 4a99cf64311c
Step 6 : RUN echo "listen_addresses='*'" >> /var/lib/pgsql/data/postgresql.conf
 ---> Using cache
 ---> 4b431bcfe6fb
Step 7 : USER postgres
 ---> Using cache
 ---> b88497ef1a95
Step 8 : ENV PGDATA /var/lib/pgsql/data
 ---> Using cache
 ---> 9272c705d631
Step 9 : EXPOSE 5432
 ---> Running in b2e4c043bc2e
 ---> a6ea2c236302
Removing intermediate container b2e4c043bc2e
Step 10 : VOLUME /etc/postgresql /var/log/postgresql /var/lib/pgsql
 ---> Running in cf06d787cecf
 ---> cffe96473050
Removing intermediate container cf06d787cecf
Step 11 : CMD /var/lib/pgsql/bin/postgres -D /var/lib/pgsql/data -c config_file=/var/lib/pgsql/data/postgresql.conf
 ---> Running in 7690289ad7cb
 ---> 1204d059861e
Removing intermediate container 7690289ad7cb
Successfully built 1204d059861e
[root@localhost ~]# cat Dockerfile
FROM fedora
MAINTAINER toto toto@cyber-neurones.org 
RUN dnf install postgresql -y 
RUN dnf install postgresql-server postgresql-contrib -y 
# Modification de la configuration 
RUN echo "host all all 0.0.0.0/0 md5" >> /var/lib/pgsql/data/pg_hba.conf 
RUN echo "listen_addresses='*'" >> /var/lib/pgsql/data/postgresql.conf 
USER postgres
ENV PGDATA /var/lib/pgsql/data
#RUN initdb --data-checksums
# Le port en ecoute 
EXPOSE 5432 
# Ajout des volumes pour faire un backup 
VOLUME ["/etc/postgresql", "/var/log/postgresql", "/var/lib/pgsql"] 
# Pour lancer postgres 
CMD ["/var/lib/pgsql/bin/postgres", "-D", "/var/lib/pgsql/data", "-c", "config_file=/var/lib/pgsql/data/postgresql.conf"]

Maintenant je lance :

[root@localhost ~]# docker run -p 5432:5432 --name postgres -e POSTGRES_PASSWORD=password -d postgres
a590ea4020c45974f68d2e9b7296d83e4176a2dca109510abd72a80b0d26fc11

[root@localhost ~]# ss -at
State       Recv-Q Send-Q                                   Local Address:Port                                                    Peer Address:Port                
LISTEN      0      128                                                  *:ssh                                                                *:*                    
LISTEN      0      100                                          127.0.0.1:smtp                                                               *:*                    
ESTAB       0      0                                         192.168.1.13:ssh                                                     192.168.1.10:62127                
LISTEN      0      128                                                 :::ssh                                                               :::*                    
LISTEN      0      128                                                 :::postgres                                                          :::*                    
LISTEN      0      100                                                ::1:smtp                                                              :::*                    
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
a590ea4020c4        postgres            "/docker-entrypoint.s"   5 minutes ago       Up 5 minutes        0.0.0.0:5432->5432/tcp   postgres

Le port semble être en écoute, maintenant il me faut perfectionner la conf de PostgreSQL et installé des outils en local afin d’avoir accès à la base.

[root@localhost ~]# yum install postgresql
[root@localhost ~]# yum install telnet

Je vais donc modifier ce fichier :

FROM fedora
MAINTAINER toto toto@cyber-neurones.org 
RUN dnf install postgresql -y 
RUN dnf install postgresql-server postgresql-contrib -y 
# Modification de la configuration 
RUN echo "host all all 0.0.0.0/0 md5" >> /var/lib/pgsql/data/pg_hba.conf 
RUN echo "listen_addresses='*'" >> /var/lib/pgsql/data/postgresql.conf 
RUN echo "tcpip_socket = true" >> /var/lib/pgsql/data/postgresql.conf 
USER postgres
ENV PGDATA /var/lib/pgsql/data
#RUN initdb --data-checksums
# Le port en ecoute 
EXPOSE 5432 
# Ajout des volumes pour faire un backup 
VOLUME ["/etc/postgresql", "/var/log/postgresql", "/var/lib/pgsql"] 
# Pour lancer postgres 
CMD ["/var/lib/pgsql/bin/postgres", "-D", "/var/lib/pgsql/data", "-c", "config_file=/var/lib/pgsql/data/postgresql.conf"]

Le but étant de faire fonctionner le connexion à la base par la suite.