Невозможно выполнить команду 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"]
Я думаю, что вы, возможно, неправильно понимаете природу инструкции 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, как только он заработает, обновлю ED2 или добавлю ED3 в качестве прямого ответа. Еще раз спасибо, Джош!
Спасибо. Я добавил дополнение, в котором описывается объединение двух
@JoshE, ну так как у меня работал ENTRYPOINT, я обновил ответ. Однако вы были правы, я не могу добиться того, чего хотел, потому что сценарий был запущен слишком рано. Сервер не читается. Хотя я добавил сон, но это тоже не сработало.
Я переместил вашу правку из этого ответа в ваш исходный вопрос, чтобы избежать путаницы. Вариант, на который вы могли бы обратить внимание, - это выполнение сценария PowerShell в ENTRYPOINT, который планирует одноразовое задание для запуска, как только сервер sql будет готов принимать команды.
@JoshE, ваш пример ED3 ENTRYPOINT
тоже работает. Мне нужно реализовать некоторую логику в сценарии PowerShell для выполнения обновления, но в любом случае вопрос не в этом :-). Большое спасибо!
Отличное описание! Я действительно пробовал с Entrypoint, о котором забыл упомянуть и добавил как 6-ю пулю. Это тоже не сработало. Я изучу это подробнее. Если вы считаете, что мой синтаксис или подход неверны, пожалуйста, помогите. Спасибо!