Dockerコンテナ内でコマンドを実行するためのdocker execの使い方
紹介
Dockerは、開発者がポータブルで一貫したLinuxコンテナを作成および管理するのを助けるコンテナ化ツールです。
コンテナを開発または展開する際には、実行中のコンテナの内部を確認して、その現在の状態を調査したり、問題をデバッグしたりする必要がよくあります。この目的のために、Dockerは既に実行中のコンテナ内でプログラムを実行するためのdocker execコマンドを提供しています。
このチュートリアルでは、docker execコマンドについて学び、それを使用してDockerコンテナ内でコマンドを実行したり、インタラクティブシェルを取得したりする方法を説明します。
DigitalOcean App Platformを使用して、GitHubからDockerアプリケーションをデプロイします。DigitalOceanにアプリのスケーリングを任せましょう。
前提条件
このチュートリアルでは、すでにDockerがインストールされており、ユーザーがdockerを実行する権限を持っていると仮定しています。もしdockerをrootユーザーとして実行する必要がある場合は、このチュートリアルのコマンドの前にsudoを付けることを忘れないでください。
Dockerをsudoなしで使用する方法に関する詳細については、当社のDockerをインストールする方法チュートリアルの「sudoなしでDockerコマンドを実行する」セクションをご覧ください。
テストコンテナの開始
docker exec コマンドを使用するには、実行中の Docker コンテナが必要です。まだコンテナを持っていない場合は、次の docker run コマンドでテストコンテナを起動してください:
docker run -d --name container-name alpine watch "date >> /var/log/date.log"
このコマンドは、公式のalpineイメージから新しいDockerコンテナを作成します。これは、軽量で最小限のLinuxディストリビューションであるAlpine Linuxを使用した人気のあるLinuxコンテナイメージです。
私たちは、ターミナルからコンテナを切り離してバックグラウンドで実行するために、-dフラグを使用します。--name container-nameはコンテナにcontainer-nameという名前を付けます。ここで好きな名前を選ぶことができますし、何も指定しなければDockerが新しいコンテナのために自動的にユニークな名前を生成します。
次に、コンテナに使用したいイメージを指定するalpineがあります。
最後に、watch "date >> /var/log/date.log"があります。これは、コンテナ内で実行したいコマンドです。watchは、デフォルトで2秒ごとに指定したコマンドを繰り返し実行します。この場合、watchが実行するコマンドはdate >> /var/log/date.logです。dateは現在の日付と時刻を印刷します。これのように:
Fri Jul 23 14:57:05 UTC 2021
コマンドの >> /var/log/date.log 部分は、date の出力をリダイレクトし、それをファイル /var/log/date.log に追加します。2秒ごとに新しい行がファイルに追加され、数秒後には次のようになります:
Fri Jul 23 15:00:26 UTC 2021
Fri Jul 23 15:00:28 UTC 2021
Fri Jul 23 15:00:30 UTC 2021
Fri Jul 23 15:00:32 UTC 2021
Fri Jul 23 15:00:34 UTC 2021
次のステップでは、Dockerコンテナの名前を見つける方法を学びます。これは、すでにターゲットにしているコンテナがあるが、その名前がわからない場合に役立ちます。
Dockerコンテナの名前を見つける
作業するコンテナの名前(またはコンテナID)を docker exec に提供する必要があります。この情報は docker ps コマンドを使用して見つけることができます:
docker ps
このコマンドはサーバー上で実行中のすべてのDockerコンテナをリストし、それらに関するいくつかの高レベルの情報を提供します:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
76aded7112d4 alpine "watch 'date >> /var…" 11 seconds ago Up 10 seconds container-name
この例では、コンテナIDと名前が強調表示されています。どちらかを使用して、docker execにどのコンテナを使用するかを指定できます。
コンテナの名前を変更したい場合は、docker rename コマンドを使用します:
docker rename container-name new-name
次に、docker execを使用してDockerコンテナ内でコマンドを実行するいくつかの例を実行します。
Dockerコンテナ内でインタラクティブシェルを実行する
Dockerコンテナ内でインタラクティブシェルを開始する必要がある場合、ファイルシステムを探索したり、実行中のプロセスをデバッグしたりするために、docker execを使用し、-iおよび-tフラグを付けてください。
-iフラグは入力をコンテナに対してオープンに保ち、-tフラグはシェルが接続できる擬似端末を作成します。これらのフラグは次のように組み合わせることができます:
docker exec -it container-name sh
これにより、指定されたコンテナ内でshシェルが実行され、基本のシェルプロンプトが表示されます。コンテナから抜け出すには、exitと入力して、ENTERを押してください。
- exit
コンテナイメージに bash などのより高度なシェルが含まれている場合は、上記の sh を bash に置き換えることができます。
Dockerコンテナ内で非対話型コマンドを実行する
実行中のDockerコンテナ内でコマンドを実行する必要があるが、インタラクティブ性が不要な場合は、フラグなしでdocker execコマンドを使用します。
docker exec container-name tail /var/log/date.log
このコマンドは、container-name コンテナ上で tail /var/log/date.log を実行し、その結果を出力します。デフォルトでは、tail コマンドはファイルの最後の10行を表示します。最初のセクションでセットアップしたデモコンテナを実行している場合、次のようなものが表示されます:
Mon Jul 26 14:39:33 UTC 2021
Mon Jul 26 14:39:35 UTC 2021
Mon Jul 26 14:39:37 UTC 2021
Mon Jul 26 14:39:39 UTC 2021
Mon Jul 26 14:39:41 UTC 2021
Mon Jul 26 14:39:43 UTC 2021
Mon Jul 26 14:39:45 UTC 2021
Mon Jul 26 14:39:47 UTC 2021
Mon Jul 26 14:39:49 UTC 2021
Mon Jul 26 14:39:51 UTC 2021
これは基本的に、Dockerコンテナ用のインタラクティブシェルを開くことと同じです(前のステップで行ったように、docker exec -it container-name shを使用する)。そして、その後にtail /var/log/date.logコマンドを実行します。しかし、シェルを開いてコマンドを実行し、その後シェルを閉じるのではなく、このコマンドは擬似端末を開くことなく、単一のコマンドで同じ出力を返します。
Dockerコンテナ内の別のディレクトリでコマンドを実行する
コンテナの特定のディレクトリでコマンドを実行するには、--workdirフラグを使用してディレクトリを指定します:
docker exec --workdir /tmp container-name pwd
この例のコマンドは、/tmp ディレクトリを作業ディレクトリとして設定し、現在の作業ディレクトリを表示する pwd コマンドを実行します:
/tmp
コマンドpwdは作業ディレクトリが/tmpであることを確認しました。
Dockerコンテナ内で異なるユーザーとしてコマンドを実行する
コンテナ内で別のユーザーとしてコマンドを実行するには、--user フラグを追加します:
docker exec --user guest container-name whoami
これにより、コンテナ内で whoami コマンドを実行するために ゲスト ユーザーが使用されます。 whoami コマンドは、現在のユーザーのユーザー名を出力します:
guest
whoami コマンドは、コンテナの現在のユーザーが guest であることを確認します。
Dockerコンテナに環境変数を渡す
時々、実行するコマンドとともに環境変数をコンテナに渡す必要があります。-eフラグを使用すると、環境変数を指定できます。
docker exec -e TEST=sammy container-name env
このコマンドは、TEST 環境変数を sammy に設定し、その後コンテナ内で env コマンドを実行します。env コマンドはすべての環境変数を出力します:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=76aded7112d4
TEST=sammy
HOME=/root
TEST 変数は sammy に設定されています。
複数の変数を設定するには、各変数ごとに-eフラグを繰り返してください:
docker exec -e TEST=sammy -e ENVIRONMENT=prod container-name env
環境変数で満たされたファイルを渡したい場合は、--env-file フラグを使用することができます。
まず、テキストエディタを使ってファイルを作成します。ここでは nano を使って新しいファイルを開きますが、自分が使いやすいエディタを使っても構いません:
nano .env
私たちはファイル名として.envを使用しています。これは、バージョン管理の外で情報を管理するための一般的な標準です。
キー=値の変数をファイルに1行ずつ書き込んでください。次のように:
TEST=sammy
ENVIRONMENT=prod
ファイルを保存して閉じます。nano でファイルを保存して終了するには、CTRL+O を押し、次に ENTER を押して保存し、最後に CTRL+X を押して終了します。
次に、--env-fileの後に正しいファイル名を指定してdocker execコマンドを実行します:
docker exec --env-file .env container-name env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=76aded7112d4
TEST=sammy
ENVIRONMENT=prod
HOME=/root
ファイル内の二つの変数が設定されています。
複数のファイルを指定するには、複数の--env-fileフラグを使用できます。ファイル内の変数が重複している場合、コマンドで最後にリストされたファイルが前のファイルを上書きします。
一般的な誤り
docker exec コマンドを使用する際に、いくつかの一般的なエラーに遭遇することがあります:
Error: No such container: container-name
そのようなコンテナエラーは、指定されたコンテナが存在しないことを意味し、コンテナ名のスペル間違いを示す可能性があります。docker psを使用して実行中のコンテナを一覧表示し、名前を再確認してください。
Error response from daemon: Container 2a94aae70ea5dc92a12e30b13d0613dd6ca5919174d73e62e29cb0f79db6e4ab is not running
この not running メッセージは、コンテナが存在するが停止していることを意味します。docker start container-name でコンテナを起動できます。
Error response from daemon: Container container-name is paused, unpause the container before exec
コンテナは一時停止中ですというエラーは、問題をかなりよく説明しています。続行する前に、docker unpause コンテナ名を使用してコンテナを一時停止解除する必要があります。
結論
このチュートリアルでは、実行中のDockerコンテナ内でコマンドを実行する方法と、それを行う際に利用できるいくつかのコマンドラインオプションについて学びました。
Dockerに関する詳細情報については、DockerチュートリアルやDocker関連のQ&AページなどへのリンクがあるDockerタグページをご覧ください。
Dockerのインストールに関するヘルプについては、「UbuntuにDockerをインストールして使用する方法」をご覧ください。