この問題はまだ解決されていませんが、run-one
コマンドを使用して簡単に回避できました ( の代わりにrun command
になりrun-one run command
、コマンドがまだ実行されている場合はエラーを返します)。
(run-one
コマンドが使用可能かどうかは で確認できますwhich run-one
)
手順:
- ネットワークを作成するスクリプトを作成します ( のようにネットワーク名をパラメーターとして受け入れる場合があります
docker network create "$1"
)。
run-one
同じネットワークに対してスクリプトが 2 回実行されていないことを確認するために を使用してスクリプトを呼び出して、ネットワークを (作成する必要がある場所に) 作成します ( run /path/to/script network-name
)。
- ?
- 利益!
以下の (デモ) スクリプトで、このアプローチの動作を確認できます。
#!/bin/bash
set -eou pipefail
RED='\033[0;31m'
NC='\033[0m' # No Color
function error {
msg="$(date '+%F %T') - ${BASH_SOURCE[0]}:${BASH_LINENO[0]}: ${*}"
>&2 echo -e "${RED}${msg}${NC}"
exit 2
}
file="${BASH_SOURCE[0]}"
command="${1:-}"
if [ -z "$command" ]; then
error "[error] no command entered"
fi
shift;
case "$command" in
"clean")
sudo docker network prune -f
;;
"test1")
run-one "$file" "test:concurrent" "test:network"
;;
"test2")
run-one "$file" "test:concurrent" "test:network:unique"
;;
"test:concurrent")
echo "===========before==========="
sudo docker network ls
echo "============================"
cmd="$1"
pids=()
for i in $(seq 1 3); do
"$file" "$cmd" &
pids["${i}"]=$!
done
idx=0
for pid in "${pids[@]}"; do
wait "$pid" && status="$?" || status="$?"
idx=$((idx + 1))
if [ "$status" != '0' ]; then
echo "error in process $pid (#$idx)"
fi
done
echo "===========after============"
sudo docker network ls
echo "============================"
;;
"test:network:unique")
run-one "$file" "test:network"
;;
"test:network")
sudo docker network create "my-network"
;;
*)
echo -e "${RED}[error] invalid command: $command${NC}"
exit 1
;;
esac
それで:
- 実行
/path/to/script clean
して未使用のネットワークを削除します (このスクリプトは必ず開発環境で実行してください)。
- を実行
/path/to/script test1
して、 という名前の 3 つのネットワークがあることを確認しますmy-network
。
- もう一度実行
/path/to/script clean
します。
- 実行
/path/to/script test2
して、名前が付けられたネットワークが 1 つしかないことを確認しますmy-network
(3 つのプロセスのうち 2 つがrun-one
コマンドによりエラーになり、1 つだけがネットワークを作成しています)。
スクリプトを作成して参照する必要があるという事実は別として、スクリプトが別の抽象化レイヤーを追加するという事実 (ネットワーク オプションを使用する場合は、複雑さが増す可能性があります) により、このソリューションはせいぜい回避策として説明されます。
とはいえ、これは簡単に達成でき、これをハックと呼ぶべきではないと思いますが、IMO の適切な解決策は Docker エンジン側 (おそらく API) にあるはずです。
これはdocker-compose
、簡単に変更できるスクリプトから実行し、事前にネットワークの名前を知っている場合を除き、タフで簡単に実現できない場合があります。