Dockerfile не может выполнить команду CMD (докер для Windows)

Невозможно выполнить команду CMD в докере для окон в файле докера.

Я хочу запустить несколько команд с помощью CMD, но не могу выполнить даже одну команду.

Я пробовал следующее, и ничего не работает ...

1.

CMD "sqlcmd -S database -i C:\db\db_scripts\upgradescript.sql -U sa -P mypassword"

2.

RUN ["powershell", "-NoProfile", "-Command", "c:\db\db_scripts\script.ps1"]

3.

CMD ["cmd", "sqlcmd", "-S", "database", "-i", "C:\db\db_scripts\upgradescript.sql", "-U", "sa", "-P", "mypassword"]

4.

ARG arg1=database
ARG arg2=C:\db\db_scripts\upgradescript.sql
ARG arg3=sa
ARG arg4=mypassword!

RUN ["cmd", "-NoProfile", "-Command", "sqlcmd -S $env:arg1 -i $env:arg2 -U $env:arg3 -P $env:arg4"]

5.

RUN powershell.exe  c:\db\db_scripts\script.ps1

6.

ENTRYPOINT ["powershell", "-NoProfile", "-Command", "sqlcmd"]
CMD ["-S database -i C:\db\db_scripts\upgradescript.sql -U sa -P mypassword"]

ПОДДЕРЖКА ФАЙЛОВ:

A. Script.ps1 (используется 2 и 5)

cmd /c "sqlcmd -S database -i C:\db\db_scripts\upgradescript.sql -U sa -P mypassword"

Б. Dockerfile

# escape=`

FROM microsoft/mssql-server-windows-developer
COPY db\* c:\db\
COPY db_scripts\* c:\db\db_scripts\
ENV attach_dbs = "[{'dbName':'ABC','dbFiles':['C:\db\ABC.mdf','C:\db\ABC_Log.ldf']},{'dbName':'XYZ','dbFiles':['C:\db\XYZ.mdf','C:\db\XYZ_Log.ldf']}]"
CMD "sqlcmd -S database -i C:\db\db_scripts\upgradescript.sql -U sa -P mypassword"

Обратите внимание, мне не нужно использовать "\\" из-за escape-символа.

НАБЛЮДЕНИЯ

Контейнер запускается и исчезает через несколько секунд.

Если я удалю часть CMD, контейнеры будут работать нормально. Я могу попасть в контейнер и запустить указанную выше команду sqlcmd в оболочке cmd.

Что я делаю не так, чего не хватает, какой-либо лучший подход и т.д. Спасибо!

Редактировать:

Основываясь на ответе Джоша, единственный способ, которым эта команда ENTRYPOINT работает для меня, - это (поделиться, чтобы другие могли получить выгоду или даже опубликовать лучший способ сделать это) ...

ENV arg1 database
ENV arg2 C:\db\db_scripts\upgradescript.sql
ENV arg3 sa
ENV arg4 mypassword
ENTRYPOINT ["powershell sleep(60); sqlcmd"]
CMD ["-S $env:arg1 -i $env:arg2 -U $env:arg3 -P $env:arg4"]
Развертывание модели машинного обучения с помощью Flask - Angular в Kubernetes
Развертывание модели машинного обучения с помощью Flask - Angular в Kubernetes
Kubernetes - это портативная, расширяемая платформа с открытым исходным кодом для управления контейнерными рабочими нагрузками и сервисами, которая...
Как создать PHP Image с нуля
Как создать PHP Image с нуля
Сегодня мы создадим PHP Image from Scratch для того, чтобы легко развернуть базовые PHP-приложения. Пожалуйста, имейте в виду, что это разработка для...
2
0
4 019
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я думаю, что вы, возможно, неправильно понимаете природу инструкции CMD по сравнению с ENTRYPOINT vs RUN. И CMD, и ENTRYPOINT вступают в силу при запуске / выполнении контейнера, тогда как RUN - это команда времени сборки. Несколько сбивает с толку то, что вы используете RUN для подготовки образа контейнера в процессе сборки докера, а CMD - это то, что запускается в контейнере.

через документация,

The main purpose of a CMD is to provide defaults for an executing container...

У любого данного образа контейнера всегда будет только одна инструкция CMD.

There can only be one CMD instruction in a Dockerfile. If you list more than one CMD then only the last CMD will take effect.

Если вы хотите убедиться, что исполняемый файл запускается при запуске контейнера, вы можете рассмотреть возможность использования инструкции ENTRYPOINT; воспринимайте ENTRYPOINT как команду, которая предоставляет значения по умолчанию для инструкции CMD. Из документов:

Dockerfile should specify at least one of CMD or ENTRYPOINT commands. ENTRYPOINT should be defined when using the container as an executable. CMD should be used as a way of defining default arguments for an ENTRYPOINT command or for executing an ad-hoc command in a container. CMD will be overridden when running the container with alternative arguments.

Команда RUN - это инструкция во время сборки, которую вы используете для подготовки образа контейнера с необходимыми файлами, конфигурацией и т. д.

См. этот ТАК вопрос для получения дополнительной информации о ENTRYPOINT и CMD.

ED: Случай, который вы рассматриваете, запуск сценария SQL в контейнере, является сложным, потому что сценарий не должен запускаться до того, как ядро ​​базы данных будет готово принять команды. Вы можете запустить сценарий обновления в инструкции ENTRYPOINT в качестве первого шага. Вы также можете рассмотреть возможность запуска сценария обновления SQL после подготовки контейнера с помощью команды docker exec.

ED2: Приведенный пример:

ENTRYPOINT ["powershell", "-NoProfile", "-Command", "sqlcmd"] CMD ["sqlcmd -S database -i C:\db\db_scripts\upgradescript.sql -U sa -P mypassword"]

не работает, потому что это приводит к тому, что, вероятно, является бессмысленной инструкцией командной строки. Помните, что CMD предоставляет параметры инструкции ENTRYPOINT, поэтому вы укажете только sqlcmd powershell в ENTRYPOINT, оставив CMD для предоставления параметров (это не проверено, OTOMH):

ENTRYPOINT powershell sqlcmd -S database -U sa -P mypassword -i

CMD C:\db\db_scripts\upgradescript.sql

ED 3: Объединив эти два оператора и добавив терминатор оператора (;) к ENTRYPOINT, вы могли бы затем разрешить запуск стандартного контейнера SQL. \ Start.ps1 script, который входит в бесконечный цикл, который предотвращает немедленную остановку контейнера (контейнеры запускаются только до тех пор, пока в них выполняется выполняемый процесс). Это гарантирует, что ваш сценарий запуска будет выполнен, даже если пользователь переопределит инструкцию CMD во время выполнения:

ENTRYPOINT powershell "sqlcmd -S database -U sa -P mypassword -i 'C:\db\db_scripts\upgradescript.sql';"

CMD .\Start.ps1

Отличное описание! Я действительно пробовал с Entrypoint, о котором забыл упомянуть и добавил как 6-ю пулю. Это тоже не сработало. Я изучу это подробнее. Если вы считаете, что мой синтаксис или подход неверны, пожалуйста, помогите. Спасибо!

wafers 09.10.2018 16:40

Я добавил потенциальный подход, чтобы попробовать

Josh E 09.10.2018 16:55

Если в моем ответе есть причина для голосования против, мне было бы полезно понять, что я сделал не так, чтобы я мог учиться и совершенствоваться в будущем. Благодарность

Josh E 09.10.2018 17:15

твой ответ отличный

user2915097 09.10.2018 17:39

Как я уже сказал, это очень хороший ответ, я просто тестирую различные комбинации Entrypoint, как только он заработает, обновлю ED2 или добавлю ED3 в качестве прямого ответа. Еще раз спасибо, Джош!

wafers 09.10.2018 17:54

Спасибо. Я добавил дополнение, в котором описывается объединение двух

Josh E 09.10.2018 18:44

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

wafers 09.10.2018 19:15

Я переместил вашу правку из этого ответа в ваш исходный вопрос, чтобы избежать путаницы. Вариант, на который вы могли бы обратить внимание, - это выполнение сценария PowerShell в ENTRYPOINT, который планирует одноразовое задание для запуска, как только сервер sql будет готов принимать команды.

Josh E 09.10.2018 19:21

@JoshE, ваш пример ED3 ENTRYPOINT тоже работает. Мне нужно реализовать некоторую логику в сценарии PowerShell для выполнения обновления, но в любом случае вопрос не в этом :-). Большое спасибо!

wafers 10.10.2018 11:30

Другие вопросы по теме