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.