Docker : collection d’images Alpine Linux pour intégration avec Consul

Depuis quelques mois, j’utilise mes propres images Docker basées sous Alpine Linux. En dehors d’un gain substantiel de volume (une instance Tomcat passe de 420 Mo avec une base Ubuntu à 170 Mo sous Alpine Linux application incluse), ces images sont destinées à une utilisation avec Consul afin de configurer et reconfigurer à chaud les services – initialisés par s6-overlay – grâce à consul-template.

Docker : erreur au build « Failed to create thread: Resource temporarily unavailable (11) »

Si vous obtenez l’erreur suivante lors du build d’une image Docker :

Failed to create thread: Resource temporarily unavailable (11)
Aborted (core dumped)

Il s’agit d’une limitation de ressources appliquée par systemd :

# systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
  Drop-In: /etc/systemd/system/docker.service.d
           └─custom.conf
   Active: active (running) since Fri 2016-03-25 10:04:16 CET; 4h 27min ago
     Docs: https://docs.docker.com
 Main PID: 927 (docker)
    Tasks: 436 (limit: 512)
   CGroup: /system.slice/docker.service
           ├─  927 /usr/bin/docker daemon -H fd:// --iptables=false --dns 8.8.8.8 --dns 8.8.4.4
           ├─10390 docker-proxy -proto tcp -host-ip 172.18.0.1 -host-port 8500 -container-ip 172.18.0.2 -container-port 8500
           ├─10411 docker-proxy -proto tcp -host-ip 172.18.0.1 -host-port 8301 -container-ip 172.18.0.2 -container-port 8301
           ├─10907 docker-proxy -proto tcp -host-ip 172.19.0.1 -host-port 61613 -container-ip 172.19.0.3 -container-port 61613
           ├─10949 docker-proxy -proto tcp -host-ip 172.19.0.1 -host-port 15672 -container-ip 172.19.0.3 -container-port 15672
           ├─10957 docker-proxy -proto tcp -host-ip 172.19.0.1 -host-port 5672 -container-ip 172.19.0.3 -container-port 5672
           ├─10965 docker-proxy -proto tcp -host-ip 172.19.0.1 -host-port 1883 -container-ip 172.19.0.3 -container-port 1883
           └─11188 docker-proxy -proto tcp -host-ip 172.19.0.1 -host-port 80 -container-ip 172.19.0.4 -container-port 80

Il convient d’augmenter le nombre de tâches autorisées, ou tout simplement désactiver cette limitation, dans le fichier service du démon docker :

# cat /etc/systemd/system/docker.service.d/custom.conf
[Service]
ExecStart=
ExecStart=/usr/bin/docker daemon -H fd:// --iptables=false --dns 8.8.8.8 --dns 8.8.4.4
TasksMax=infinity
# systemctl daemon-reload
# systemctl restart docker.service

Maven : vérifier les mises à jour disponibles

Vérifier les mises à jour des plugins Maven :

boris@debian:~$ mvn versions:display-plugin-updates

Vérifier les mises à jour des dépendances du projet :

boris@debian:~$ mvn versions:display-dependency-updates

NetworkManager : désactiver la gestion d’une interface réseau

Par défaut, NetworkManager s’accapare de la gestion de toutes les interfaces réseaux. Dans le cadre de l’utilisation de système de virtualisation, ceci est problématique. Il est nécessaire de désactiver cette gestion en précisant soit le nom/regex de l’interface réseau, soit son adresse MAC.

Voici un exemple couvrant ces deux cas :

boris@debian:~$ vim /etc/NetworkManager/NetworkManager.conf
[main]
plugins=ifupdown,keyfile

[ifupdown]
managed=false

[keyfile]
unmanaged-devices=interface-name:vboxnet*;interface-name:docker0
unmanaged-devices=mac:74:da:38:60:15:cd
boris@debian:~$ sudo systemctl restart network-manager

Firefox : supprimer la configuration HSTS d’un site

L’effacement de l’historique Firefox ne supprimer pas la configuration HSTS. Pour y remédier, l’édition du fichier SiteSecurityServiceState.txt présent dans votre profil est obligatoire :

# cd ~/.mozilla/firefox/eue6le58.dev-edition-default/
# vim SiteSecurityServiceState.txt

Supprimez la ou les lignes concernées.

Nginx : création d’un fichier htpasswd avec openssl

boris@debian:~$ printf "USER:$(openssl passwd -crypt PASSWORD)\n" > vhost.htpasswd

Maven : construire une image Docker et y intégrer le JAR du projet

Le but est de construire l’image Docker d’un projet Java par Maven. L’image est générée par le plugin Maven docker-maven-plugin mais afin de ne pas casser le versioning, le nom du JAR original n’est pas modifié; une copie est réalisée avant intégration (un nom de fichier fixe est obligatoire).

Au niveau du projet Maven, un répertoire dédié est créé pour le Dockerfile et l’ensemble des fichiers de génération de l’image :

bhuisgen@local:~/Projects/java/demo$ find src/main/docker/
src/main/docker/
src/main/docker/Dockerfile
src/main/docker/root
src/main/docker/root/etc
src/main/docker/root/etc/services.d
src/main/docker/root/etc/services.d/app
src/main/docker/root/etc/services.d/app/finish
src/main/docker/root/etc/services.d/app/run

L’image repose sur une base Alpine Linux avec gestion des services par s6-overlay auquel est ajouté le strict nécessaire :

bhuisgen@local:~/Projects/java/demo$ cat src/main/docker/Dockerfile
FROM bhuisgen/alpine-base:latest
MAINTAINER Boris HUISGEN <bhuisgen@hbis.fr>

RUN apk add --update openjdk8-jre && \
    rm -rf /var/cache/apk/*

COPY root /

ENTRYPOINT ["/init"]
CMD []

A noter que la commande de copie du JAR n’est pas présente; le plugin l’ajoutera de lui-même. Le reste est donc à ajouter au fichier POM :

bhuisgen@local:~/Projects/java/demo$ vim pom.xml

[...]

    <build>
        <plugins>

[...]

            <!-- copy and rename the JAR to a fixed filename -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-antrun-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <configuration>
                            <target>
                                <copy
                                    file="${project.build.directory}/${project.artifactId}-${project.version}.jar"
                                    tofile="${project.build.directory}/app.jar" />
                            </target>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

            <!-- build the Docker image -->
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>0.4.0</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>build</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <imageName>${docker.image.prefix}/${project.artifactId}</imageName>
                    <imageTag>${project.version}</imageTag>
                    <imageTag>latest</imageTag>
                    <dockerDirectory>src/main/docker</dockerDirectory>
                    <resources>
                        <resource>
                            <directory>${project.build.directory}</directory>
                            <include>app.jar</include>
                            <targetPath>/</targetPath>
                        </resource>
                    </resources>
                </configuration>
            </plugin>

L’image sera générée lors de la phase package et un tag y sera appliqué pour conserver le numéro de version de l’application.

OpenSSH : accès au prompt

Raccourci-clavier : [Entrée] + [~] + [?]

~?
Supported escape sequences:
 ~.   - terminate connection (and any multiplexed sessions)
 ~B   - send a BREAK to the remote system
 ~C   - open a command line
 ~R   - request rekey
 ~V/v - decrease/increase verbosity (LogLevel)
 ~^Z  - suspend ssh
 ~#   - list forwarded connections
 ~&   - background ssh (when waiting for connections to terminate)
 ~?   - this message
 ~~   - send the escape character by typing it twice
(Note that escapes are only recognized immediately after newline.)

Boto : gérer le logging

Pour activer le log de debug :

import logging
logging.basicConfig(filename="boto.log", level=logging.DEBUG)

Pour supprimer tout le logging (par exemple avec S3) hormis les erreurs critiques :

import logging
logging.getLogger('boto').setLevel(logging.CRITICAL)

Amazon EC2 : scripts de gestion des disques éphémères

Voici les scripts et unités systemd que j’utilise pour gérer les disques éphémères de mes instances Amazon EC2.

Haut de page