1
votes

Est-il possible d'ajouter un programme d'installation, de l'exécuter et de le supprimer au cours d'une étape de construction dans Docker?

J'essaye de créer une image Docker à partir d'un binaire d'installation assez volumineux (300+ Mo). Je souhaite ajouter le programme d'installation à l'image, l'installer et supprimer le programme d'installation. Cela ne semble pas possible:

COPY huge-installer.bin /tmp
RUN /tmp/huge-installer.bin
RUN rm /tmp/huge-installer.bin   # <- has no effect on the image size

L'utilisation de plusieurs étapes de construction ne semble pas résoudre ce problème, car je dois exécuter le programme d'installation dans l'image finale. Si je pouvais exécuter le programme d'installation directement à partir d'une étape de construction précédente, sans le copier, cela résoudrait mon problème, mais pour autant que je sache, ce n'est pas possible.

Y a-t-il un moyen d'éviter d'inclure le poids complet du programme d'installation dans l'image finale?


2 commentaires

Avez-vous encore trouvé le temps d'essayer l'une des solutions proposées?


@bellackn Oui, merci de me l'avoir rappelé. Aucune des solutions ne m'était applicable. J'ai trouvé une solution alternative en utilisant un serveur HTTP pour héberger mon répertoire de projet. Je l'ai ajouté comme réponse.


3 Réponses :


0
votes

Je pense que le meilleur moyen est de télécharger le bac à partir d'un site Web puis de l'exécuter:

RUN wget http://myweb/huge-installer.bin && /tmp/huge-installer.bin && rm /tmp/huge-installer.bin

de cette manière, votre couche d'image ne contiendra pas le binaire que vous téléchargez

p>


0 commentaires

0
votes

Je ne l'ai pas testé à fond, mais une telle approche ne serait-elle pas viable? (Outre la réponse de LinPy, ce qui est beaucoup plus facile si vous avez la possibilité de le faire de cette façon.)

Dockerfile:

$ docker build -t foo-1
$ docker run --rm --name foo-1 --rm -d -v $(pwd)/your-installer:/tmp/your-installer
$ docker logs -f foo-1
# once it echoes "commit me now!", run the next command
$ docker commit foo-1 foo-2
$ docker stop foo-1

entrypoint.sh:

#!/bin/sh

/tmp/your-installer # install your stuff here

while true; do
  echo "installer finished, commit me now!"
  sleep 5
done

Puis exécutez:

FROM alpine:latest

COPY entrypoint.sh /tmp/entrypoint.sh
RUN \
  echo "I am an image that can run your huge installer binary!" \
  && echo "I will only function when you give it to me as a volume mount."

ENTRYPOINT [ "/tmp/entrypoint.sh" ]

Comme le programme d'installation n'a été monté que sous forme de volume, l'image foo-2 code > ne devrait plus le contenir. Vous pouvez également aller construire un autre Dockerfile basé sur foo-2 pour changer le point d'entrée, par exemple.

Cf. docker commit

p>


0 commentaires

1
votes

J'ai fini par résoudre ce problème en utilisant le serveur HTTP intégré en Python pour rendre le répertoire du projet disponible pour l'image via HTTP.

Dans le Dockerfile, je peux exécuter des commandes comme celle-ci, en envoyant des scripts directement à bash en utilisant curl:

SHELL := bash
IMAGE_NAME := app-test
VERSION := 1.0.0
SERVER_PORT := 8580

.ONESHELL:

.PHONY: build
build:
    # Kills the HTTP server when the build is done
    function cleanup {
        pkill -f "python3 -m http.server.*${SERVER_PORT}"
    }
    trap cleanup EXIT

    # Starts a HTTP server that makes the contents of the project directory 
    # available to the image
    python3 -m http.server -b 127.0.0.1 ${SERVER_PORT} &>/dev/null &
    sleep 1

    EXTRA_ARGS=""

    # Allows skipping the build cache by setting NO_CACHE=1
    if [[ -n $$NO_CACHE ]]; then
        EXTRA_ARGS="--no-cache"
    fi

    docker build $$EXTRA_ARGS \
        --network host \
        --build-arg SERVER_PORT=${SERVER_PORT} \
        -t ${IMAGE_NAME}:latest \
        .

    docker tag ${IMAGE_NAME}:latest ${IMAGE_NAME}:${VERSION}

Ou enregistrez les binaires, exécutez-les et supprimez-les en une seule étape:

RUN curl -O "http://127.0.0.1:${SERVER_PORT}/binary-${INSTALLER_VERSION}.bin" && \
    ./binary-${INSTALLER_VERSION}.bin && \
    rm binary-${INSTALLER_VERSION}.bin

J'utilise un Makefile pour Démarrez le serveur et arrêtez-le après la construction, mais vous pouvez utiliser un script de construction à la place.

Voici un exemple de Makefile:

RUN curl "http://127.0.0.1:${SERVER_PORT}/installer-${INSTALLER_VERSION}.bin" | bash


0 commentaires