質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Docker

Dockerは、Docker社が開発したオープンソースのコンテナー管理ソフトウェアの1つです

Q&A

解決済

2回答

941閲覧

Node.jsからインタラクティブな別コマンドへ処理を移行したい

kotatsu_hal

総合スコア34

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Docker

Dockerは、Docker社が開発したオープンソースのコンテナー管理ソフトウェアの1つです

1グッド

0クリップ

投稿2018/05/07 06:57

概要

通常、コマンドラインから docker run -it centos とタイプして実行すると、新たなdockerコンテナが作成されその中でプロンプトが出、入力待ち状態になります。

イメージ説明
これを Node.js から実行させるようなコマンドラインツールを作成中です。(イメージは node tool.js --centos-cli みたいな感じ)
単純に、Node.jsの処理を終えて上記の docker コマンドへ処理を移行したいだけなので、ラクショーかと思っていたのですが、一向に実現できません・・。

##確認環境

  • Windows 10 Pro
  • Docker CommunityEdition (Engine: 18.03.1-ce) ※Hyper-V
  • Node.js v8.9.2

やったこと/考察

まずは以下のように exec() で書いてみました。

js

1const child = require('child_process') 2child.exec('docker run -it centos')

ところが、何も起きません。docker コンテナも作られません。
イメージ説明
処理を待った方がいいのかなと思い exec()execSync() に替えたところ、今度は the input device is not a TTY. If you are using mintty, try prefixing the command with 'winpty' というエラーメッセージが表示されました。
イメージ説明

いろいろ検索していたところ、海外の質問サイトで外部コマンドでPDFファイルを開きたい旨の投稿を見つけたので、参考にして以下のコードを書きました。 exec() ではなく spawn() を使っています。
How to detach a spawned child process in a Node.js script?

js

1const child = require('child_process'); 2let cp = child.spawn('docker', ['run', '-it', 'centos'], { 3 detached: true, 4 stdio: 'ignore' 5}) 6cp.unref();

結果は、 exec() と同様、なにも起きず、コンテナも作成されずに終了してしまいます。
同様に spawn()spawnSync() にすると、unref() が関数ではないというエラーが出ました。

イメージ説明

##お願いします
いろいろやってわかったのは、child.exec('start https://google.com') など、実行してすぐ終わるようものなら正常に動くのですが、インタラクティブに入出力を受け付けるようなコマンドはうまく動かないということでした。

このへんを見てTTY自体を実装しないといけないということなんでしょうかね・・?
単純に Node.js 終了させて docker コマンドを実行したいだけなんですが・・。

何か方法がございましたらお知恵を拝借したく存じます。
よろしくお願いします。
m(_ _)m

miyabi-sun👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

私の場合はcentosではなくnodeイメージのコンテナでしたが、
下記のコードで動かす事に成功しましたので、コードを貼り付けます。

JavaScript

1const {spawn} = require('child_process'); 2spawn('docker', ['run', '-it', 'centos', 'bash'], {stdio: 'inherit'});

原因に関しては

まずstdio: 'ignore'で標準入出力殺してますね。
stdio: 'inherit'にしてください。

次にdockerコマンドは最後にやりたいコマンドを末尾に指定する必要があります。
ですので、今回はbashコマンドをひっつけました。

参考になったのは英語版stack overflowのSpawning a child process with tty in node.js

投稿2018/05/07 08:32

編集2018/05/07 08:34
miyabi-sun

総合スコア21158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kotatsu_hal

2018/05/07 08:44

ご回答ありがとうございました! おっしゃる通り`inherit` で無事動きました! 感動しました!
kotatsu_hal

2018/05/07 08:46

うちのプログラムだと `spawn()` だとちょっと入力こぼれが発生してたようなので、`spawnSync()` にしました。これでバッチシでした!
miyabi-sun

2018/05/07 08:56

spawnだと入力こぼれ!? そうなんですね。でも動いて良かったです!
guest

0

最後に書いてありますが、startを使うのはダメですか。
コマンドプロンプト側で別プロセス上げる方法ですがどうでしょう。

js

1const child = require('child_process') 2child.exec('start docker run -it centos')

こちらの環境では確認済みです。
nodejsのみversion違いでver:6.1.0です。
別ウィンドウで入力を受け付けれます。

投稿2018/05/07 08:33

szk.

総合スコア1400

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kotatsu_hal

2018/05/07 08:45

ご確認いただきありがとうございました! 参考にします!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問