web-dev-qa-db-ja.com

特定の名前のDockerコンテナーが存在しない場合にのみBashコマンドを実行する方法は?

Jenkinsマシンでは、(シェルスクリプト内に)存在しない場合にのみ、指定された名前でdockerコンテナを作成します。コマンドを実行してコンテナを作成し、失敗があればそれを無視してもよいと考えましたが、これによりジェンキンスのジョブが失敗します。

したがって、Dockerコンテナが存在するかどうか、bashを使用していないかどうかを確認する方法を知りたいと思います。

50
kshah

<name>をgrepすることで、実行中のコンテナが存在しないことを確認し、後で次のように起動できます。

[ ! "$(docker ps -a | grep <name>)" ] && docker run -d --name <name> <image>

より良い:

https://docs.docker.com/engine/reference/commandline/ps/ を使用し、終了したコンテナがブロックするかどうかを確認します。これにより、コンテナを実行する前にまずコンテナを削除できます。

if [ ! "$(docker ps -q -f name=<name>)" ]; then
    if [ "$(docker ps -aq -f status=exited -f name=<name>)" ]; then
        # cleanup
        docker rm <name>
    fi
    # run your container
    docker run -d --name <name> my-docker-image
fi
90
ferdy

filterおよびformatなどのUNIXユーティリティでのパイピングを回避するために、docker psコマンドにgrepおよびawkオプションを使用できます。

name='nginx'

[[ $(docker ps --filter "name=^/$name$" --format '{{.Names}}') == $name ]] ||
docker run -d --name mynginx <nginx-image>
26
anubhava

私は考えます

docker container inspect <container-name> || docker run...

docker container inspect呼び出しは$?コンテナが存在しない場合は1になり(検査できない)、存在する場合は0になります(これは停止したコンテナに関連します)。そのため、コンテナが期待どおりに存在しない場合に実行コマンドが呼び出されます。

19
WiRai

名前の前に^ /を付け、接尾辞に$を付けます。それは正規表現のようです:

CONTAINER_NAME='mycontainername'

CID=$(docker ps -q -f status=running -f name=^/${CONTAINER_NAME}$)
if [ ! "${CID}" ]; then
  echo "Container doesn't exist"
fi
unset CID
6
yucer

docker top でさらに短くなります:

docker top <name> || docker run --name <name> <image>

docker topは、実行中の名前に一致するコンテナがない場合にゼロ以外を返します。それ以外の場合は、pid、ユーザー、実行時間、およびコマンドを返します。

4
Blaise

文書化されていない動作のない堅牢なgrep ^$

これは私が見つけることができる最も正確で柔軟なアプローチです:

container_name=mycont
if Sudo docker ps -a --format '{{.Names}}' | grep -Eq "^${container_name}\$"; then
  echo exists
else
  echo 'does not exist'
fi

根拠:

  1. https://stackoverflow.com/a/38576401/895245 は、コンテナ名が別のコンテナのサブストリングである場合は機能しません
  2. https://stackoverflow.com/a/45171589/895245 および https://stackoverflow.com/a/43202632/895245 見つけられなかった動作に依存ドキュメント:docker container inspectの終了ステータスとその-f nameは何らかの正規表現を取ります。

Python

Pythonバージョンは、プロジェクトで使用することになったので便利です。

containers = subprocess.check_output([
        'Sudo',
        'docker',
        'ps',
        '-a',
        '--format', '{{.Names}}',
]).decode()
if container_name in containers.split():
    # Exists.
if [[ $(Sudo docker inspect --format . <container-name>) == "." ]]; then
  docker run <container-name>;
fi

説明

すでに同様の応答があります。ここでの違いは--format .オプションです(-f .も使用できます)。これにより、inspectコマンドからすべての詳細が削除されます。 Dockerは go template format を使用します。この場合、認識されないものはすべて出力にコピーされます。

そのため、namexを持つコンテナが終了すると、-f itIsThereitIsThereを返します。そうでない場合、dockerはエラーコードとメッセージ(Error: No such object: <container-name>)を返します。

Jenkinsログでこれを見つけました。

1
Fernando César

次のコードを使用して、Dockerコンテナが存在するかどうかを判断します。

CONTAINER_NAME='my_docker_container'
# Checking if docker container with $CONTAINER_NAME name exists.
COUNT=$(docker ps -a | grep "$CONTAINER_NAME" | wc -l)
if (($COUNT > 0)); then
    echo 'container exists'
fi
1
Aliaksei Maniuk