Запустить докер в фоновом режиме под Powershell

Простой вопрос, я хочу запустить команду docker в фоновом режиме.
(На самом деле, выполнение любой команды с параметрами командной строки в Powershell - это мой реальный вопрос, но docker - простой конкретный вопрос)

У меня есть команда

docker run -ti --rm -e DISPLAY=$DISPLAY firefox

который отлично работает под Powershell, но блокируется.

Я хочу запустить эквивалентный метод выполнения «&», как в * nix:

docker run -ti --rm -e DISPLAY=$DISPLAY firefox &

я пробовал

но у меня ничего не работает:

> ping google.com &
At line:1 char:17
+ ping google.com &
+                 ~
The ampersand (&) character is not allowed.

> Start-Process "C:\Program Files\Docker\Docker\resources\bin\docker.exe" run -ti --rm -e DISPLAY=$DISPLAY firefox
Start-Process : Parameter cannot be processed because the parameter name 'e' is ambiguous. Possible
matches include: -ErrorAction -ErrorVariable.
At line:1 char:86
+ ... Files\Docker\Docker\resources\bin\docker.exe" run -ti --rm -e DISPLAY ...
+                                                                ~~
    + CategoryInfo          : InvalidArgument: (:) [Start-Process], ParameterBindingException
    + FullyQualifiedErrorId : AmbiguousParameter,Microsoft.PowerShell.Commands.StartProcessCommand

Пытался обернуть всю команду в Start-Process { ... }, тоже не работает.

[ОБНОВЛЕНИЕ / Сводка]

Принятые ответы работают (после того, как я удалил «-ti» из командной строки), как сказал @nischay goyal, «пожалуйста, не используйте -it, поскольку он открывает терминал и блокирует его».. Я получил ошибку:

the input device is not a TTY.  If you are using mintty, try prefixing the command with 'winpty'
    + CategoryInfo          : NotSpecified: (the input devic...d with 'winpty':String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError
    + PSComputerName        : localhost
  • Таким образом, Start-Job может не подходить в качестве универсального способа выполнения "&", например, если я хочу начать bash & таким образом.

  • Однако Start-Process работает после передачи всех остальных docker параметров командной строки параметру -ArgumentList в виде одной строки.

  • И, конечно же, как говорят все люди из лагеря docker / Linux, используйте -d.

В общем, есть много способов решить проблему. Выберите тот, который вам подходит.


person xpt    schedule 29.03.2020    source источник


Ответы (4)


Используйте Start-Job, чтобы запустить команду в PowerShell в фоновом режиме.

В PowerShell [Core] 6+ вы также можете поместить & в конце вашей команды, так же, как вы можете в POSIX-подобных оболочках, таких как Bash.

В обоих случаях возвращается объект задания (System.Management.Automation.PSRemotingJob), которым можно управлять с помощью различных *-Job командлетов - см. about_Jobs.

Задания в PowerShell похожи на задания в POSIX-подобных оболочках (например, Bash), но есть некоторые фундаментальные различия, в частности <сильные > невозможность запускать интерактивные команды в фоновом режиме - см. этот комментарий на GitHub.

Фоновые задания используют дочерний процесс, который запускает скрытый экземпляр PowerShell в фоновом режиме, что является медленным и ресурсоемким.

Поэтому рассмотрите поток на основе Start-ThreadJob в качестве более быстрой и легкой альтернативы - см. этот ответ.

Синтаксис, который работает и в версиях PowerShell ниже 6, с Start-Job:

# Preferable alternative: Start-ThreadJob
$job = Start-Job { docker run --rm -e DISPLAY=$using:DISPLAY firefox }

Примечание. -ti был удален, потому что, как указывает Нишай Гоял, он открывал интерактивный сеанс оболочки, что означает, что вызов не вернется, пока этот сеанс не будет закрыт вручную. Однако не то чтобы Start-Job обычно не поддерживает запуск интерактивных программ в фоновом режиме, поскольку объяснено здесь.

Обратите внимание на необходимость ссылаться на переменную $DISPLAY в области действия вызывающего через спецификатор области $using: - см. about_Remote_Variables.

Предостережение: в версиях PowerShell до 6.x фоновые задания, запускаемые таким образом, использовали фиксированный рабочий каталог, не связанный с вызывающим - см. этот ответ.

Альтернатива PowerShell [Core] 6+: размещение & в конце команды:

$job = docker run --rm -e DISPLAY=$DISPLAY firefox &

Обратите внимание, что вам не нужен спецификатор области $using: с этим синтаксисом, и даже в PowerShell 6.x задание видит тот же рабочий каталог, что и вызывающий.

Обратите внимание, что не существует аналогичного краткого синтаксиса для создания заданий thread (эквивалент вызова Start-ThreadJob) в PowerShell 7.0, но его добавление является предметом запрос этой функции на GitHub.


Как уже говорилось, вы можете использовать различные другие *-Job командлеты для управления заданием после его создания (они также управляют потоковыми заданиями, созданными с помощью Start-ThreadJob); например, следующая команда синхронно ожидает завершения задания, распечатывает его вывод, а затем удаляет задание.

$job | Receive-Job -Wait -AutoRemoveJob

Что касается того, что вы пробовали:

Постпозиционный & в ping google.com & не работал, потому что вы работаете в Windows PowerShell (версии PowerShell до v5.1), тогда как для этого синтаксиса требуется PowerShell [Core] версии 6 или выше.

Start-Process предназначен для запуска исполняемый файл асинхронно и в новом окне по умолчанию (в Windows).
Это в первую очередь полезно для запуска приложений с графическим интерфейсом (асинхронно) или выполнения команд оболочки в новом окне консоли.

Хотя он также может запускать процессы незаметно, вы получаете небольшой контроль над этим процессом, а его выходные данные могут быть захвачены только косвенно, через текстовые файлы.

Причина, по которой ваш вызов не удался, заключается в том, что вы пытались передать сквозные аргументы напрямую в Start-Process, вместо того, чтобы передавать их в параметр -ArgumentList (в простейшем случае как одну строку).

person mklement0    schedule 30.03.2020

Команда firefox не ожидает ввода на стандартный ввод и не требует tty. Так что удалите -it. Затем добавьте -d, который означает отключенный режим, стандартный способ запуска демонов внутри докера или другие неинтерактивные команды.

docker run -d --rm -e DISPLAY=$DISPLAY firefox
person BMitch    schedule 29.03.2020
comment
Спасибо, однако обратите внимание, что это вопрос больше о Powershell, чем о докере. То есть запуск любой команды с параметрами командной строки в Powershell - это мой реальный вопрос. - person xpt; 30.03.2020

Чтобы запустить контейнер докеров в автономном режиме, не используйте -it, поскольку он открывает терминал и блокирует его.

docker run --rm -e DISPLAY=$DISPLAY firefox

Для запуска команды в фоновом режиме в PowerShell, пока команда является исполняемым файлом или файлом, который имеет связанный исполняемый файл, используйте Start-Process (доступно в v2):

Start-Process -NoNewWindow ping google.com
person nischay goyal    schedule 29.03.2020

чтобы полностью выполнить команду в докере с докером в фоновом режиме, вы можете использовать:

docker run $YourOption $ImageDocker exec $yourCommand 

и не используйте параметры -i -t, он открывает терминал

сделай что-нибудь вроде

docker run --rm -e DISPLAY=$DISPLAY firefox exec "ping google.com"
person lamourette jean-baptiste    schedule 29.03.2020