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

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Time limit is exhausted. Please reload CAPTCHA.