425 lines
12 KiB
Plaintext
425 lines
12 KiB
Plaintext
|
#!/bin/bash
|
||
|
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
||
|
# Script permettant de lancer une commande dans docker et/ou de bootstrapper
|
||
|
# l'utilisation de nulib dans un projet
|
||
|
# Les fichiers suivants doivent être copiés à un endroit quelconque du projet:
|
||
|
# - rundk (ce script)
|
||
|
# - Dockerfile.rundk
|
||
|
# Les fichiers suivants peuvent être intégrés dans le projet comme exemples:
|
||
|
# - dot-build.env.dist
|
||
|
# - dot-dkbuild.env.dist
|
||
|
# Par défaut, ce script assume que bootstrap est copié dans le répertoire sbin/
|
||
|
# du projet, et que le fichier composer.json et le répertoire vendor/ sont à la
|
||
|
# racine du projet. Le cas échéant, modifier les valeurs ci-dessous
|
||
|
MYDIR="$(cd "$(dirname -- "$0")"; pwd)"
|
||
|
MYNAME="$(basename -- "$0")"
|
||
|
MYSELF="$MYDIR/$MYNAME"
|
||
|
|
||
|
################################################################################
|
||
|
# Modifier les valeurs suivantes si nécessaire
|
||
|
|
||
|
# répertoire du projet. ce chemin doit être absolu
|
||
|
PROJDIR=
|
||
|
|
||
|
# composer: répertoire du projet composer (celui qui contient le fichier
|
||
|
# composer.json), chemin de composer.phar et répertoire vendor. ces chemions
|
||
|
# doivent être relatifs à $PROJDIR
|
||
|
COMPOSERDIR=
|
||
|
COMPOSERPHAR=
|
||
|
VENDORDIR=
|
||
|
|
||
|
# fichier de configuration pour le build
|
||
|
BUILDENV=
|
||
|
|
||
|
################################################################################
|
||
|
# Ne pas modifier à partir d'ici
|
||
|
|
||
|
[ -n "$PROJDIR" ] || PROJDIR="$(dirname -- "$MYDIR")"
|
||
|
[ -n "$COMPOSERDIR" ] || COMPOSERDIR=.
|
||
|
[ -n "$COMPOSERPHAR" ] || COMPOSERPHAR=sbin/composer.phar
|
||
|
[ -n "$VENDORDIR" ] || VENDORDIR=vendor
|
||
|
[ -n "$BUILDENV" ] || BUILDENV=build.env
|
||
|
|
||
|
[ "$COMPOSERPHAR" == none ] && COMPOSERPHAR=
|
||
|
[ "$BUILDENV" == none ] && BUILDENV=
|
||
|
|
||
|
function eecho() { echo "$*" 1>&2; }
|
||
|
function eerror() { eecho "ERROR: $*"; }
|
||
|
function die() { [ $# -gt 0 ] && eerror "$*"; exit 1; }
|
||
|
function in_path() { [ -n "$1" -a -x "$(which "$1" 2>/dev/null)" ]; }
|
||
|
function composer() {
|
||
|
cd "$PROJDIR/$COMPOSERDIR" || exit 1
|
||
|
if [ -x "$PROJDIR/$COMPOSERPHAR" ]; then
|
||
|
"$PROJDIR/$COMPOSERPHAR" "$@"
|
||
|
elif in_path composer; then
|
||
|
command composer "$@"
|
||
|
elif [ -x /usr/bin/composer ]; then
|
||
|
/usr/bin/composer "$@"
|
||
|
elif [ -x /usr/local/bin/composer ]; then
|
||
|
/usr/local/bin/composer "$@"
|
||
|
else
|
||
|
die "impossible de trouver composer"
|
||
|
fi
|
||
|
if [ -f composer.lock ]; then
|
||
|
cp composer.lock "$PROJDIR/.composer.lock.rundk"
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
bootstrap=
|
||
|
BootstrapOnly=1
|
||
|
ForcedBootstrap=
|
||
|
args=()
|
||
|
for arg in "$@"; do
|
||
|
if [ "$arg" == --bootstrap ]; then
|
||
|
bootstrap=1
|
||
|
elif [ "$arg" == --exec ]; then
|
||
|
BootstrapOnly=
|
||
|
else
|
||
|
args+=("$arg")
|
||
|
fi
|
||
|
done
|
||
|
set -- "${args[@]}"
|
||
|
|
||
|
if [ -z "$bootstrap" ]; then
|
||
|
# si vendor/ n'existe pas, alors on doit faire bootstrap
|
||
|
if [ ! -f "$PROJDIR/$VENDORDIR/nulib/php/load.sh" ]; then
|
||
|
ForcedBootstrap=1
|
||
|
elif [ ! -f "$PROJDIR/.composer.lock.rundk" ]; then
|
||
|
ForcedBootstrap=1
|
||
|
elif ! diff -q "$PROJDIR/$COMPOSERDIR/composer.lock" "$PROJDIR/.composer.lock.rundk" >&/dev/null; then
|
||
|
ForcedBootstrap=1
|
||
|
elif [ -n "$bootstrap" -a -n "$BootstrapOnly" ]; then
|
||
|
# bootstrap inutile
|
||
|
exit 0
|
||
|
fi
|
||
|
|
||
|
if [ -n "$ForcedBootstrap" ]; then
|
||
|
[ -z "$_RUNDK_IN_DOCKER" ] && eecho "== rundk bootstrap is needed"
|
||
|
bootstrap=1
|
||
|
BootstrapOnly=
|
||
|
fi
|
||
|
fi
|
||
|
|
||
|
if [ -z "$_RUNDK_IN_DOCKER" ]; then
|
||
|
############################################################################
|
||
|
# Lancement depuis l'extérieur du container
|
||
|
|
||
|
## Charger ~/.dkbuild.env
|
||
|
|
||
|
APT_PROXY="$RUNDK_APT_PROXY"
|
||
|
APT_MIRROR="$RUNDK_APT_MIRROR"
|
||
|
SEC_MIRROR="$RUNDK_SEC_MIRROR"
|
||
|
TIMEZONE="$RUNDK_TIMEZONE"
|
||
|
PRIVAREG="$RUNDK_PRIVAREG"
|
||
|
REGISTRY="$RUNDK_REGISTRY"
|
||
|
IMAGE="$RUNDK_IMAGE"
|
||
|
PROFILE=
|
||
|
HOST_MAPPINGS=()
|
||
|
function default_profile() {
|
||
|
PROFILE="$1"
|
||
|
}
|
||
|
function profile() {
|
||
|
local profile
|
||
|
for profile in "$@"; do
|
||
|
[ "$profile" == "$PROFILE" ] && return 0
|
||
|
done
|
||
|
return 1
|
||
|
}
|
||
|
function setenv() {
|
||
|
eval "export $1"
|
||
|
}
|
||
|
function default() {
|
||
|
local command="$1"; shift
|
||
|
local nv n v
|
||
|
case "$command" in
|
||
|
docker)
|
||
|
for nv in "$@"; do
|
||
|
[[ "$nv" == *=* ]] || continue
|
||
|
n="${nv%%=*}"
|
||
|
v="${nv#*=}"
|
||
|
case "$n" in
|
||
|
host-mappings)
|
||
|
read -a ns <<<"$v"
|
||
|
for v in "${ns[@]}"; do
|
||
|
HOST_MAPPINGS+=("$v")
|
||
|
done
|
||
|
;;
|
||
|
esac
|
||
|
done
|
||
|
;;
|
||
|
esac
|
||
|
}
|
||
|
[ -f ~/.dkbuild.env ] && source ~/.dkbuild.env
|
||
|
|
||
|
[ -n "$APT_PROXY" ] || APT_PROXY=
|
||
|
[ -n "$APT_MIRROR" ] || APT_MIRROR=default
|
||
|
[ -n "$SEC_MIRROR" ] || SEC_MIRROR=default
|
||
|
[ -n "$TIMEZONE" ] || TIMEZONE=Europe/Paris
|
||
|
[ -n "$PRIVAREG" ] || PRIVAREG=
|
||
|
[ -n "$REGISTRY" ] || REGISTRY=pubdocker.univ-reunion.fr
|
||
|
|
||
|
## Construire l'image
|
||
|
|
||
|
if [ -n "$RUNDK_NO_USE_RSLAVE" ]; then
|
||
|
UseRslave=
|
||
|
elif [ -n "$RUNDK_USE_RSLAVE" ]; then
|
||
|
UseRslave=1
|
||
|
elif [ -e /proc/sys/fs/binfmt_misc/WSLInterop ]; then
|
||
|
# pas de mount propagation sous WSL
|
||
|
UseRslave=
|
||
|
else
|
||
|
UseRslave=1
|
||
|
fi
|
||
|
IMAGENAME=nulib/rundk
|
||
|
|
||
|
if [ -n "$bootstrap" ]; then
|
||
|
BUILD_ARGS=(
|
||
|
REGISTRY
|
||
|
APT_PROXY
|
||
|
APT_MIRROR
|
||
|
SEC_MIRROR
|
||
|
TIMEZONE
|
||
|
)
|
||
|
|
||
|
SOPTS=+c:UjDx:z:r:pw:v
|
||
|
LOPTS=help,config:,unless-exists,pull,no-cache,plain-output,apt-proxy:,timezone:,privareg:,push,chdir:,verbose,no-use-rslave
|
||
|
args="$(getopt -n "$MYNAME" -o "$SOPTS" -l "$LOPTS" -- "$@")" || exit 1; eval "set -- $args"
|
||
|
|
||
|
[ -f "$PROJDIR/$BUILDENV" ] && Config="$PROJDIR/$BUILDENV" || Config=
|
||
|
Build=
|
||
|
UnlessExists=
|
||
|
Pull=
|
||
|
NoCache=
|
||
|
PlainOutput=
|
||
|
Chdir=
|
||
|
Verbose=
|
||
|
while [ $# -gt 0 ]; do
|
||
|
case "$1" in
|
||
|
--) shift; break;;
|
||
|
--help)
|
||
|
eecho "\
|
||
|
rundk: construire l'image docker
|
||
|
|
||
|
USAGE
|
||
|
$MYNAME --bootstrap [options...] [--exec command [args...]]
|
||
|
|
||
|
OPTIONS
|
||
|
-c, --config build.env
|
||
|
--unless-exists
|
||
|
-U, --pull
|
||
|
-j, --no-cache
|
||
|
-D, --plain-output
|
||
|
-x, --apt-proxy APT_PROXY
|
||
|
-z, --timezone TIMEZONE
|
||
|
-r, --privareg PRIVAREG
|
||
|
-p, --push
|
||
|
paramètres pour la consruction de l'image
|
||
|
-w, --chdir CHDIR
|
||
|
aller dans le répertoire spécifié avant de lancer la commande
|
||
|
-v, --verbose
|
||
|
afficher plus d'informations"
|
||
|
exit 0
|
||
|
;;
|
||
|
-c|--config) shift; Config="$1";;
|
||
|
-0|--build) Build=1;;
|
||
|
--unless-exists) UnlessExists=1;;
|
||
|
-U|--pull) Pull=1;;
|
||
|
-j|--no-cache) NoCache=1;;
|
||
|
-D|--plain-output) PlainOutput=1;;
|
||
|
-x|--apt-proxy) shift; APT_PROXY="$1";;
|
||
|
-z|--timezone) shift; TIMEZONE="$1";;
|
||
|
-r|--privareg) shift; PRIVAREG="$1";;
|
||
|
-p|--push) Push=1;;
|
||
|
-w|--chdir) shift; Chdir="$1";;
|
||
|
-v|--verbose) Verbose=1;;
|
||
|
--no-use-rslave) UseRslave=;;
|
||
|
*) die "$1: option non configurée";;
|
||
|
esac
|
||
|
shift
|
||
|
done
|
||
|
|
||
|
[ "$Config" == none ] && Config=
|
||
|
if [ -n "$Config" ]; then
|
||
|
source "$Config" || exit 1
|
||
|
fi
|
||
|
if [ -z "$IMAGE" ]; then
|
||
|
[ -n "$PRIVAREG" ] && IMAGE="$PRIVAREG/$IMAGENAME" || IMAGE="$REGISTRY/$IMAGENAME"
|
||
|
fi
|
||
|
if [ -z "$UnlessExists" -o -z "$(docker image ls --no-trunc --format '{{.Repository}}:{{.Tag}}' "$IMAGE" 2>/dev/null)" ]; then
|
||
|
eecho "== Building $IMAGE"
|
||
|
args=(
|
||
|
-f "$MYDIR/Dockerfile.rundk"
|
||
|
${Pull:+--pull}
|
||
|
${NoCache:+--no-cache}
|
||
|
${BuildPlain:+--progress plain}
|
||
|
-t "$IMAGE"
|
||
|
)
|
||
|
for arg in "${BUILD_ARGS[@]}"; do
|
||
|
args+=(--build-arg "$arg=${!arg}")
|
||
|
done
|
||
|
mkdir -p /tmp/rundk-build
|
||
|
docker build "${args[@]}" /tmp/rundk-build || exit 1
|
||
|
|
||
|
if [ -n "$Push" -a -n "$PRIVAREG" ]; then
|
||
|
eecho "== Pushing $IMAGE"
|
||
|
docker push "$IMAGE" || exit 1
|
||
|
fi
|
||
|
fi
|
||
|
[ -n "$BootstrapOnly" ] && exit 0
|
||
|
|
||
|
else
|
||
|
SOPTS=+w:v
|
||
|
LOPTS=help,chdir:,verbose,no-use-rslave
|
||
|
args="$(getopt -n "$MYNAME" -o "$SOPTS" -l "$LOPTS" -- "$@")" || exit 1; eval "set -- $args"
|
||
|
|
||
|
Chdir=
|
||
|
Verbose=
|
||
|
while [ $# -gt 0 ]; do
|
||
|
case "$1" in
|
||
|
--) shift; break;;
|
||
|
--help)
|
||
|
eecho "\
|
||
|
rundk: construire l'image docker
|
||
|
|
||
|
USAGE
|
||
|
$MYNAME ci|cu|composer
|
||
|
$MYNAME --exec [options...] command [args...]
|
||
|
|
||
|
COMMANDES COMPOSER
|
||
|
ci
|
||
|
cu
|
||
|
installer/mettre à jour les dépendances du projet avec composer
|
||
|
composer (args...]
|
||
|
lancer composer avec les arguments spécifiés.
|
||
|
|
||
|
pour les commandes ci-dessus, l'option --chdir est ignorée: le répertoire
|
||
|
courant est forcé au répertoire du projet composer
|
||
|
|
||
|
OPTIONS
|
||
|
-w, --chdir CHDIR
|
||
|
aller dans le répertoire spécifié avant de lancer la commande
|
||
|
-v, --verbose
|
||
|
afficher plus d'informations"
|
||
|
exit 0
|
||
|
;;
|
||
|
-w|--chdir) shift; Chdir="$1";;
|
||
|
-v|--verbose) Verbose=1;;
|
||
|
--no-use-rslave) UseRslave=;;
|
||
|
*) die "$1: option non configurée";;
|
||
|
esac
|
||
|
shift
|
||
|
done
|
||
|
|
||
|
if [ -z "$IMAGE" ]; then
|
||
|
[ -n "$PRIVAREG" ] && IMAGE="$PRIVAREG/$IMAGENAME" || IMAGE="$REGISTRY/$IMAGENAME"
|
||
|
fi
|
||
|
fi
|
||
|
|
||
|
## Lancer la commande
|
||
|
|
||
|
uid="$(id -u)"
|
||
|
gid="$(id -g)"
|
||
|
args=(
|
||
|
run -it --rm
|
||
|
--name rundk
|
||
|
-e _RUNDK_IN_DOCKER=1
|
||
|
-e _RUNDK_UID="$uid"
|
||
|
-e _RUNDK_GID="$gid"
|
||
|
)
|
||
|
for host in "${HOST_MAPPINGS[@]}"; do
|
||
|
args+=(--add-host "$host")
|
||
|
done
|
||
|
|
||
|
# monter le répertoire qui contient $PROJDIR
|
||
|
mount_composer=
|
||
|
if [ "${PROJDIR#$HOME/}" != "$PROJDIR" -o "$PROJDIR" == "$HOME" ]; then
|
||
|
# bind mount $HOME
|
||
|
args+=(-v "$HOME:$HOME${UseRslave:+:rslave}")
|
||
|
else
|
||
|
# bind mount uniquement le répertoire du projet
|
||
|
args+=(-v "$PROJDIR:$PROJDIR${UseRslave:+:rslave}")
|
||
|
mount_composer=1
|
||
|
fi
|
||
|
if [ -n "$mount_composer" -a -d "$HOME/.composer" ]; then
|
||
|
# monter la configuration de composer
|
||
|
args+=(-v "$HOME/.composer:$HOME/.composer")
|
||
|
fi
|
||
|
args+=(-w "$(pwd)")
|
||
|
|
||
|
# lancer avec l'utilisateur courant
|
||
|
if [ $uid -ne 0 ]; then
|
||
|
# si c'est un utilisateur lambda, il faut monter les informations
|
||
|
# nécessaires. composer est déjà monté via $HOME
|
||
|
user="$(id -un)"
|
||
|
userent="$(getent passwd "$user")"
|
||
|
group="$(id -gn)"
|
||
|
groupent="$(getent group "$group")"
|
||
|
args+=(
|
||
|
-e _RUNDK_USER="$user"
|
||
|
-e _RUNDK_USERENT="$userent"
|
||
|
-e _RUNDK_GROUPENT="$groupent"
|
||
|
)
|
||
|
fi
|
||
|
|
||
|
args+=(
|
||
|
"$IMAGE"
|
||
|
exec "$MYSELF" ${Chdir:+-w "$Chdir"}
|
||
|
)
|
||
|
[ -n "$ForcedBootstrap" ] && set -- ci
|
||
|
[ -n "$Verbose" ] && eecho "\$ docker ${args[*]} $*"
|
||
|
exec docker "${args[@]}" "$@"
|
||
|
|
||
|
else
|
||
|
############################################################################
|
||
|
# Lancement depuis l'intérieur du container
|
||
|
|
||
|
# Ajouter les informations utilisateur le cas échéant
|
||
|
if [ -n "$_RUNDK_USERENT" ]; then
|
||
|
grep -q "^$_RUNDK_USER:" /etc/passwd || echo "$_RUNDK_USERENT" >>/etc/passwd
|
||
|
fi
|
||
|
if [ -n "$_RUNDK_GROUPENT" ]; then
|
||
|
grep -q "^$_RUNDK_GROUP:" /etc/group || echo "$_RUNDK_GROUPENT" >>/etc/group
|
||
|
fi
|
||
|
if [ -n "$_RUNDK_USER" ]; then
|
||
|
user="$_RUNDK_USER"
|
||
|
export _RUNDK_USER=
|
||
|
export _RUNDK_USERENT=
|
||
|
export _RUNDK_GROUPENT=
|
||
|
if in_path su-exec; then
|
||
|
exec su-exec "$user" "$0" "$@"
|
||
|
else
|
||
|
exec runuser -u "$user" -- "$0" "$@"
|
||
|
fi
|
||
|
fi
|
||
|
|
||
|
SOPTS=+w:
|
||
|
LOPTS=chdir:
|
||
|
args="$(getopt -n "$MYNAME" -o "$SOPTS" -l "$LOPTS" -- "$@")" || exit 1; eval "set -- $args"
|
||
|
|
||
|
chdir=
|
||
|
action=
|
||
|
while [ $# -gt 0 ]; do
|
||
|
case "$1" in
|
||
|
--) shift; break;;
|
||
|
-w|--chdir) shift; chdir="$1";;
|
||
|
*) die "$1: option non configurée";;
|
||
|
esac
|
||
|
shift
|
||
|
done
|
||
|
|
||
|
if [ "$1" == ci ]; then
|
||
|
eecho "== installing composer dependencies"
|
||
|
composer i
|
||
|
elif [ "$1" == cu ]; then
|
||
|
eecho "== upgrading composer dependencies"
|
||
|
composer u
|
||
|
elif [ "$1" == composer ]; then
|
||
|
"$@"
|
||
|
else
|
||
|
if [ -n "$chdir" ]; then
|
||
|
cd "$chdir" || exit 1
|
||
|
fi
|
||
|
command "${@:-bash}"
|
||
|
fi
|
||
|
fi
|