Archives pour la catégorie ‘Docker’

Docker : inspecter les commandes healthcheck

Pour voir en temps réel les commandes healthcheck effectuées sur chacun des containers :

$ docker system events --filter event=exec_start
2017-01-19T14:53:32.979634882+01:00 container exec_start: /bin/sh -c /etc/cont-consul/check || exit 1 fa7c8221a53e2a76e61f290c4008f67ea2548b923cc42a11e9234ee0db4cab54 (com.docker.compose.config-hash=b4b13e5e0066bd757aa944cc01869736eb1d150ac04516e19028d070ef5f502c, com.docker.compose.container-number=1, com.docker.compose.oneoff=False, com.docker.compose.project=dev, com.docker.compose.service=zabbix-agent, com.docker.compose.version=1.9.0, image=registry.foobot.io/foobot/zabbix-agent, name=dev_zabbix-agent_1)
2017-01-19T14:53:33.985556968+01:00 container exec_start: /bin/sh -c /etc/cont-consul/check || exit 1 a009ecbbb3cdce6da2bdf6ae073b9d323bcc2921eafc82206f7e4719e37a617a (com.docker.compose.config-hash=2e83302dfa763cf4185883bed56a64cd8e9207d3a78f06fd250bc158aafedde6, com.docker.compose.container-number=1, com.docker.compose.oneoff=False, com.docker.compose.project=dev, com.docker.compose.service=rabbitmq, com.docker.compose.version=1.9.0, image=registry.foobot.io/foobot/rabbitmq, name=dev_rabbitmq_1)
2017-01-19T14:53:35.252389013+01:00 container exec_start: /bin/sh -c /etc/cont-consul/check || exit 1 a7398fd76d95544ac6cd8d02fbacb9608d5fd3443c1afb4fa0b4606dc032476c (com.docker.compose.config-hash=3c3cae569ff98e6a7e91b8e6734bfed22e9c5df90c8bd593539ef4876e2bda25, com.docker.compose.container-number=1, com.docker.compose.oneoff=False, com.docker.compose.project=dev, com.docker.compose.service=mariadb, com.docker.compose.version=1.9.0, image=registry.foobot.io/foobot/mariadb, name=dev_mariadb_1)
2017-01-19T14:53:39.875116453+01:00 container exec_start: /bin/sh -c /etc/cont-consul/check || exit 1 1f41e9a3b5b63601042dbf5dcd758342e217f0f5d5685d76e9f61b2a2c155a5a (com.docker.compose.config-hash=733b83db2c39e867d08158e3101decdc5e3d70fa0653fea7f44139e29b47d2fa, com.docker.compose.container-number=1, com.docker.compose.oneoff=False, com.docker.compose.project=dev, com.docker.compose.service=dynamodb, com.docker.compose.version=1.9.0, image=registry.foobot.io/foobot/dynamodb, name=dev_dynamodb_1)

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 : 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.

Docker : activer les restrictions RAM & swap

# vim /etc/default/grub 
GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"
# update-grub
# vim /etc/default/docker
DOCKER_OPTS="--exec-opt native.cgroupdriver=cgroupfs"
# shutdown -r now

Debian : fix startup Docker 1.7 & kernel 4.1

sept. 20 19:34:19 muse systemd[1]: Started Docker Application Container Engine.
sept. 20 19:34:19 muse docker[18643]: time="2015-09-20T19:34:19.773439875+02:00" level=error msg="[graphdriver] prior storage driver \"aufs\" failed: driver not supported"
sept. 20 19:34:19 muse docker[18643]: time="2015-09-20T19:34:19.773487551+02:00" level=fatal msg="Error starting daemon: error initializing graphdriver: driver not supported"
# rm -rf /var/lib/docker/aufs
# systemctl start docker

Docker : supprimer tous les containers à l’arrêt

# docker rm $(docker ps -a|grep "Exited"|awk "{print \$1}")

Docker : cleanup des images orphelines d’un registre privé

#!/bin/bash
set -eu

shopt -s nullglob

base_dir=$1
if [ -z "$base_dir" ] ; then
    echo "$0 <DIR>"
    exit 1;
fi

readonly output_dir=$(mktemp -d -t trace-images-XXXX)
readonly jq=$(which jq)

readonly repository_dir=$base_dir/repositories
readonly image_dir=$base_dir/images

readonly all_images=$output_dir/all
readonly used_images=$output_dir/used
readonly unused_images=$output_dir/unused

function image_history() {
    local readonly image_hash=$1

    $jq '.[]' $image_dir/$image_hash/ancestry | tr -d '"'
}

echo "Collecting orphan images at $repository_dir"
for library in $repository_dir/*; do
    echo "Library $(basename $library)"

    for repo in $library/*; do
        echo "- $(basename $repo)" >&2

        for tag in $repo/tag_*; do
            echo "  + $(basename $tag)" >&2

            tagged_image=$(cat $tag)
            image_history $tagged_image
        done
    done
done | sort | uniq > $used_images

ls $image_dir > $all_images

grep -v -F -f $used_images $all_images > $unused_images || true

readonly all_image_count=$(wc -l $all_images | awk '{print $1}')
readonly used_image_count=$(wc -l $used_images | awk '{print $1}')
readonly unused_image_count=$(wc -l $unused_images | awk '{print $1}')

readonly unused_image_size=$( if [ $unused_image_count -gt 0 ] ; then \
    cd $image_dir; du -hc $(cat $unused_images) | tail -n1 | cut -f1; \
else echo 0; fi
    )

if [ $unused_image_count -le 0 ] ; then
    echo "No unused images, exiting";
    exit 0;
fi

echo -e "\nTrimming _index_images..."
readonly unused_images_flatten=$output_dir/unused.flatten
cat $unused_images | sed -e 's/\(.*\)/\"\1\" /' | tr -d "\n" > $unused_images_flatten

for library in $repository_dir/*; do
    echo "Library $(basename $library)" >&2

    for repo in $library/*; do
        echo " Repo $(basename $repo)" >&2
        mkdir -p "$output_dir/$(basename $repo)"
        jq '.' "$repo/_index_images" > "$output_dir/$(basename $repo)/_index_images.old"
        jq -s '.[0] - [ .[1:][] | {id: .} ]' "$repo/_index_images" $unused_images_flatten > "$output_dir/$(basename $repo)/_index_images"
        cp "$output_dir/$(basename $repo)/_index_images" "$repo/_index_images"
    done
done

echo ""
echo "These are unused images:"
cat $unused_images
echo "${all_image_count} images, ${used_image_count} used, ${unused_image_count} unused, size ${unused_image_size}"

echo ""
echo "Cleaning unused images"
cat $unused_images | xargs -I{} rm -rf $image_dir/{}

Docker : lancer un shell dans un container

Depuis Docker version 1.3 :

# docker exec -ti container_name /bin/bash

CoreOS : cloud config pour instance EC2 avec stockage local Docker + swap

Le fichier cloud-config ci-dessous initialise une instance EC2 CoreOS avec les options suivantes :

  • paramétrage des timeout fleet et etcd
  • swap d’1 Go sur le disque local (/dev/xvdb1)
  • partition BRTFS pour les containers Docker sur disque local (/dev/xvdb2)
  • désactivation du reboot automatique par sécurité (locksmithd)
#cloud-config

coreos:
  update:
    reboot-strategy: off
  etcd:
    # generate a new token for each unique cluster from https://discovery.etcd.io/new
    discovery: https://discovery.etcd.io/7c024472504cf1cef428ccc8af8e63f0
    # multi-region and multi-cloud deployments need to use $public_ipv4
    addr: $private_ipv4:4001
    peer-addr: $private_ipv4:7001
    peer-election-timeout: 6000
    peer-heartbeat-interval: 1500
    snapshot: true
    snapshot-count: 100
  fleet:
    public-ip: $public_ipv4
    metadata: region=eu-west
    etcd-request-timeout: 1500
  units:
    - name: etcd.service
      command: start
    - name: fleet.service
      command: start
    - name: format-ephemeral.service
      command: start
      content: |
        [Unit]
        Description=Formats the ephemeral drive
        [Service]
        Type=oneshot
        RemainAfterExit=yes
        ExecStartPre=/usr/sbin/wipefs -f /dev/xvdb
        ExecStartPre=/usr/bin/sh -c "(/usr/bin/echo ',1024,S' && /usr/bin/echo ';')|/usr/sbin/sfdisk /dev/xvdb -uM"
        ExecStartPre=/usr/sbin/mkswap -f /dev/xvdb1
        ExecStartPre=/usr/sbin/swapon /dev/xvdb1
        ExecStart=/usr/sbin/mkfs.btrfs -f /dev/xvdb2
    - name: var-lib-docker.mount
      command: start
      content: |
        [Unit]
        Description=Mount ephemeral to /var/lib/docker
        Requires=format-ephemeral.service
        After=format-ephemeral.service
        Before=docker.service
        [Mount]
        What=/dev/xvdb2
        Where=/var/lib/docker
        Type=btrfs
Haut de page