#!/bin/bash # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 source "$(dirname "$0")/lib/ulib/auto" || exit 1 function display_help() { uecho "$scriptname: outil pour faciliter l'utilisation de docker USAGE $scriptname CMDs... COMMANDES build push start, run service stop up logs down brd bs ps ls rm prune OPTIONS -d, --chdir PROJDIR -p, --profile PROFILE -P, --prod -T, --test -n, --fake -j, --no-cache -h, --host HOST" } function get_version() { local GIT_DIR; unset GIT_DIR if git rev-parse --git-dir >/dev/null 2>&1; then local head commit tag commit="$(git rev-list --tags --max-count=1 2>/dev/null)" if [ -n "$commit" ]; then tag="$(git describe --tags "$commit" 2>/dev/null)" if [ -n "$tag" ]; then head="$(git rev-parse HEAD)" if [ "$commit" != "$head" ]; then echo "$tag-develop" else echo "$tag" fi return fi fi elif [ -f VERSION.txt ]; then cat VERSION.txt fi echo develop } function docker_add_build_arg() { eval "replace_build_args+=(--build-arg $1=\"$2\"); $1=\"$2\"" } function docker_parse_build_args() { cat "$1" | grep -v '^#' | grep -v '^$' | sed -r 's/([^=]+)=(.*)/replace_build_args+=(--build-arg \1="\2"); \1="\2"/' } function docker_parse_env_args() { [ -f .build.env ] && eval "$(docker_parse_build_args .build.env)" [ -f build.env ] && eval "$(docker_parse_build_args build.env)" [ -n "$PROFILE" -a -f ".build.$PROFILE.env" ] && eval "$(docker_parse_build_args ".build.$PROFILE.env")" } function docker_set_env_args() { [ -f .build.env ] && source ./.build.env [ -f build.env ] && source ./build.env [ -n "$PROFILE" -a -f ".build.$PROFILE.env" ] && source "./.build.$PROFILE.env" } function docker_set_run_args() { replace_run_args+=(--env-file "$1") source "$1" } function docker_check_name() { [ -n "$NAME" ] || die "Vous devez définir NAME dans .build.env" if [ "$1" == set_container_name ]; then project_name="$NAME" container_name="${project_name//[^a-zA-Z0-9_-]/}" [ -n "$PROFILE" ] && container_name="${container_name}_$PROFILE" fi } function compose_set_env_args() { replace_env_args+=(-f docker-compose.yml) if [ -f docker-compose.override.yml ]; then replace_env_args+=(-f docker-compose.override.yml) fi local PROJECT_NAME=--none-- [ -f .compose.env ] && source ./.compose.env if [ -n "$PROFILE" ]; then if [ -f "docker-compose.$PROFILE.yml" ]; then replace_env_args+=(-f "docker-compose.$PROFILE.yml") fi if [ "$PROJECT_NAME" != --none-- ]; then if [ -z "$COMPOSE_PROJECT_NAME" ]; then [ -n "$PROJECT_NAME" ] || PROJECT_NAME="$(basename -- "$(pwd)")" COMPOSE_PROJECT_NAME="${PROJECT_NAME}_${PROFILE}" fi export COMPOSE_PROJECT_NAME fi fi if [ "$1" == set_container_name ]; then if [ "$PROJECT_NAME" == --none-- ]; then project_name="$(basename -- "$(pwd)")" else project_name="$PROJECT_NAME" fi container_name="${project_name//[^a-zA-Z0-9_-]/}" [ -n "$PROFILE" ] && container_name="${container_name}_$PROFILE" fi } function host_run() { # lancer le script $2..@ sur l'hôte $1 # si $1 n'est pas défini ou est le nom l'hôte local, lancer le script en # local avec les droits root # sinon, si docker-machine existe, l'hôte doit correspondre à la machine active # sinon, lancer inconditionnellement le script sur l'hôte distant local host="$1" script="$2"; shift; shift if [ -n "$host" ]; then if check_hostname "$host"; then estep "Lancement de $script localement" runscript_as_root "$script" "$@" elif progexists docker-machine; then local dm; setx dm=docker-machine active 2>/dev/null if [ "${host%%.*}" == "$dm" ]; then estep "Copie du script vers root@$host" scp "$script" "root@$host:/tmp/tmp-dk-service-script" || die estep "Lancement du script à distance" local -a args; args=(/tmp/tmp-dk-service-script "$@") ssh -qt "root@$host" "$(qvals "${args[@]}"); rm -f /tmp/tmp-dk-service-script" else ewarn "La machine active ($dm) n'est pas la destination ($host)" fi else estep "Copie du script vers root@$host" scp "$script" "root@$host:/tmp/tmp-dk-service-script" || die estep "Lancement du script à distance" local -a args; args=(/tmp/tmp-dk-service-script "$@") ssh -qt "root@$host" "$(qvals "${args[@]}"); rm -f /tmp/tmp-dk-service-script" fi else estep "Lancement de $script localement" runscript_as_root "$script" "$@" fi } function local_run() { # lancer le script $2..@ sur l'hôte $1 uniquement si c'est l'hôte courant local host="$1" script="$2"; shift; shift if [ -n "$host" ]; then if ! check_hostname "$host"; then eerror "Cette commande doit obligatoirement être lancée depuis l'hôte $host" return 1 fi fi estep "Lancement de $script localement" runscript_as_root "$script" "$@" } function initialize_build_env() { CTXDIR=. NAME= TAGS=(latest) VERSION= } function default_update_build_env() { [ -n "$VERSION" ] || docker_add_build_arg VERSION "$(get_version)" [ -n "$VERSION" ] && TAGS+=("$VERSION") } function update_build_env() { default_update_build_env; } function default_compose_build() { ${FAKE:+qvals} docker-compose \ "${replace_env_args[@]}" "${env_args[@]}" \ build \ ${NO_CACHE:+--no-cache} \ "${replace_build_args[@]}" "${build_args[@]}" \ "$@" } function default_docker_build() { local tag for tag in "${TAGS[@]}"; do replace_build_args+=(-t "$NAME:$tag") done ${FAKE:+qvals} docker build \ ${NO_CACHE:+--no-cache} \ "${replace_env_args[@]}" "${env_args[@]}" \ "${replace_build_args[@]}" "${build_args[@]}" \ "$@" "$CTXDIR" } function compose_build() { default_compose_build "$@"; } function docker_build() { default_docker_build "$@"; } function auto_build() { local -a replace_env_args env_args local -a replace_build_args build_args initialize_build_env if [ -f docker-compose.yml ]; then compose_set_env_args update_build_env compose_build else docker_parse_env_args docker_check_name docker_add_build_arg build_date "$(date +%y%m%d)" update_build_env docker_build fi } function auto_push() { local -a replace_env_args env_args local -a replace_build_args build_args local tag initialize_build_env if [ -f docker-compose.yml ]; then compose_set_env_args update_build_env else docker_parse_env_args docker_check_name update_build_env fi for tag in "${TAGS[@]}"; do ${FAKE:+qvals} docker push "$NAME:$tag" done } function default_compose_up() { ${FAKE:+qvals} docker-compose \ "${replace_env_args[@]}" "${env_args[@]}" \ up "${replace_run_args[@]}" "${run_args[@]}" \ "${replace_user_args[@]}" "${user_args[@]}" "$@" } function default_docker_up() { ${FAKE:+qvals} docker run \ "${replace_env_args[@]}" "${env_args[@]}" \ "${replace_run_args[@]}" "${run_args[@]}" \ "$NAME" \ "${replace_user_args[@]}" "${user_args[@]}" "$@" } function compose_up() { default_compose_up "$@"; } function docker_up() { default_docker_up "$@"; } function auto_up() { local -a replace_env_args env_args local -a replace_run_args run_args local -a replace_user_args user_args local project_name container_name if [ -f docker-compose.yml ]; then compose_set_env_args replace_run_args=(-d) compose_up "$@" else docker_set_env_args docker_check_name set_container_name replace_run_args=(-d --name "$container_name") docker_up "$@" fi } function default_compose_service() { local docker_compose="$(which docker-compose 2>/dev/null)" if [ -z "$docker_compose" ]; then if [ -x /usr/bin/docker-compose ]; then docker_compose=/usr/bin/docker-compose elif [ -x /usr/local/bin/docker-compose ]; then docker_compose=/usr/local/bin/docker-compose else die "Impossible de trouver docker-compose" fi fi setx startcmd=qvals "$docker_compose" \ "${replace_env_args[@]}" "${env_args[@]}" \ up "${replace_run_args[@]}" "${run_args[@]}" \ "${replace_user_args[@]}" "${user_args[@]}" "$@" setx stopcmd=qvals "$docker_compose" down } function default_docker_service() { local docker="$(which docker 2>/dev/null)" if [ -z "$docker" ]; then if [ -x /usr/bin/docker ]; then docker=/usr/bin/docker elif [ -x /usr/local/bin/docker ]; then docker=/usr/local/bin/docker else die "Impossible de trouver docker" fi fi setx startcmd=qvals "$docker" run \ "${replace_env_args[@]}" "${env_args[@]}" \ "${replace_run_args[@]}" "${run_args[@]}" \ "$NAME" \ "${replace_user_args[@]}" "${user_args[@]}" "$@" setx stopcmd=qvals "$docker" stop "$container_name" } function compose_service() { default_compose_service "$@"; } function docker_service() { default_docker_service "$@"; } function auto_service() { local -a replace_env_args env_args local -a replace_run_args run_args local -a replace_user_args user_args local project_name container_name startcmd stopcmd local tmpscript; ac_set_tmpfile tmpscript estep "Génération du service" export COMPOSE_PROJECT_NAME= if [ -f docker-compose.yml ]; then compose_set_env_args set_container_name replace_run_args=(-d --no-color) compose_service "$@" if [ -z "$HOST" -a -f .env ]; then source ./.env if [ -n "$PROFILE" ]; then HOST="${PROFILE^^}_HOST"; HOST="${!HOST}" fi fi else docker_set_env_args docker_check_name set_container_name replace_run_args=(-d --name "$container_name") docker_service "$@" fi [ -n "$COMPOSE_PROJECT_NAME" ] || COMPOSE_PROJECT_NAME="$project_name" chmod 755 "$tmpscript" cat >"$tmpscript" </etc/systemd/system/$container_name.service </dev/null for dm_profile in "${DM_PROFILES[@]}"; do splitpair "$dm_profile" dm profile if [ "$dm" == "$active_dm" ]; then DEFAULT_PROFILE="$profile" break fi done fi chdir= FAKE= NO_CACHE= HOST= args=( --help '$exit_with display_help' -d:,--chdir: chdir= -p:,--profile: PROFILE= -P,--prod PROFILE=prod -T,--test PROFILE=test -n,--fake FAKE=1 -j,--no-cache NO_CACHE=1 -h:,--host: HOST= ) parse_args "$@"; set -- "${args[@]}" # construire par défaut [ $# -eq 0 ] && set -- build [ -n "$PROFILE" ] || PROFILE="$DEFAULT_PROFILE" [ -n "$chdir" ] && { cd "$chdir" || die; } while [ $# -gt 0 ]; do [ "$1" == -- ] && { shift; continue; } cmd="$1"; shift case "$cmd" in b|build) [ -f .build.scripts.sh ] && source ./.build.scripts.sh [ -f build.scripts.sh ] && source ./build.scripts.sh args=() while [ $# -gt 0 -a "$1" != -- ]; do args+=("$1"); shift done enote "Profil $PROFILE" auto_build "${args[@]}" || die ;; push) [ -f .build.scripts.sh ] && source ./.build.scripts.sh [ -f build.scripts.sh ] && source ./build.scripts.sh args=() while [ $# -gt 0 -a "$1" != -- ]; do args+=("$1"); shift done enote "Profil $PROFILE" auto_push "${args[@]}" || die ;; s|run|start) args=() while [ $# -gt 0 -a "$1" != -- ]; do args+=("$1"); shift done enote "Profil $PROFILE" auto_up "${args[@]}" || die ;; service) args=() while [ $# -gt 0 -a "$1" != -- ]; do args+=("$1"); shift done enote "Profil $PROFILE" auto_service "${args[@]}" || die ;; k|stop) args=() while [ $# -gt 0 -a "$1" != -- ]; do args+=("$1"); shift done enote "Profil $PROFILE" auto_stop "${args[@]}" || die ;; 1|up) args=() while [ $# -gt 0 -a "$1" != -- ]; do args+=("$1"); shift done enote "Profil $PROFILE" auto_up "${args[@]}" && auto_logs || die ;; l|logs) args=() while [ $# -gt 0 -a "$1" != -- ]; do args+=("$1"); shift done enote "Profil $PROFILE" auto_logs "${args[@]}" || die ;; 0|down) args=() while [ $# -gt 0 -a "$1" != -- ]; do args+=("$1"); shift done enote "Profil $PROFILE" auto_down "${args[@]}" || die ;; d|brd) do_auto_down=1 function auto_down_trap() { [ -n "$do_auto_down" ] && auto_down } trap auto_down_trap 1 3 15 EXIT [ -f .build.scripts.sh ] && source ./.build.scripts.sh [ -f build.scripts.sh ] && source ./build.scripts.sh args=() while [ $# -gt 0 -a "$1" != -- ]; do args+=("$1"); shift done enote "Profil $PROFILE" if auto_build; then auto_up "${args[@]}" && auto_logs || die else do_auto_down= fi ;; bs) [ -f .build.scripts.sh ] && source ./.build.scripts.sh [ -f build.scripts.sh ] && source ./build.scripts.sh args=() while [ $# -gt 0 -a "$1" != -- ]; do args+=("$1"); shift done enote "Profil $PROFILE" auto_build && auto_up "${args[@]}" ;; ps) docker container ps -a || die;; ls) docker image ls || die;; rm) args=() while [ $# -gt 0 -a "$1" != -- ]; do args+=("$1"); shift done docker image rm "${args[@]}" || die ;; X|prune) docker container prune -f || die docker image prune -f || die ;; *) die "$cmd: commande inconnue";; esac done