- Docker WORKDIR не создает папку
- 1 ответ
- Это совершенно нормально.
- Оригинальный ответ
- Исправление проблем под Docker. Казалось бы, при чём здесь GIT?
- Постскриптум
- Dockerfile and Docker run -w / workdir
- 1 Answer 1
- Docker WORKDIR path добавляется к относительному пути
- 3 ответа
- Опция 1
- Option2
- What is the point of WORKDIR on Dockerfile?
- 6 Answers 6
Docker WORKDIR не создает папку
Я новичок в Docker, я использовал Visual Studio 2017 для добавления поддержки Docker, поэтому в основном он просто создает Dockerfile в папке проекта.
Я переместил Dockerfile в папку решения, которая находится на 1 уровень выше папки проекта, после чего сборка докеров прошла правильно.
НО затем я присмотрелся и обнаружил, что папка src не создается.
Сначала я получил последний образ и запустил его:
докер запустить b60b91d0d89f
Затем я нашел новый контейнер
Затем я врезался в контейнер
1 ответ
Это совершенно нормально.
В вашем файле dockerfile используется многоступенчатая сборка. Вы должны прочитать об этом документацию. По сути, у вас есть один этап (база), который представляет собой изображение, которое вы публикуете, и другой этап (сборка), на котором вы будете создавать и публиковать свое приложение.
Все, что вы делаете на этапе сборки, не будет опубликовано, за исключением случаев, когда вы явно скопируете это в окончательное изображение.
В вашем файле докеров указано, что вы копируете исходный код в каталог / src на этапе сборки. Затем вы собираете и публикуете его, все еще на стадии сборки. Как только это будет сделано, вы скопируете результаты со стадии сборки на базовую стадию. Это то, что делает инструкция COPY —from=publish /app . .
Это позволяет публиковать более светлое изображение. Обратите внимание, что базовый образ — это microsoft/dotnet:2.2-aspnetcore-runtime , тогда как образ сборки основан на более тяжелом microsoft/dotnet:2.2-sdk .
Оригинальный ответ
Проблема не в том, что каталог /src или /src/dockerapi не существует в вашем изображении. Это файл dockerapi/dockerapi.csproj , которого нет на вашем хосте.
Это просто ошибка относительного пути. Вы выполняете команду сборки docker из каталога C:\temp\playground\dockerapp\dockerapi . Это означает, что контекст сборки — это каталог dockerapi .
Когда вы выполняете эту строку COPY [«dockerapi/dockerapi.csproj», «dockerapi/»] , докер ищет файл C:\temp\playground\dockerapp\dockerapi\dockerapi\dockerapi.csproj (обратите внимание на \dockerapi\dockerapi ), которого не существует.
Попробуйте изменить контекст сборки докера, выполнив команду сборки из папки dockerapp и передав путь к Dockerfile.
Источник
Исправление проблем под Docker. Казалось бы, при чём здесь GIT?
Докер под Windows — это постоянные приключения. То ему нужно обновить операционку, иначе последние версии не ставятся, то он забывает, как подключаться к сети. В общем, каждый день от него новости. «Поставил и забыл» — это не про Docker Desktop for Windows. Особенно, когда он используется не совсем так, как рекомендуют его разработчики. А они почему-то не одобряют подключение внешних windows сетевых дисков в качестве локальных. И совсем не одобряют доступ к к таким сетевым папкам, которые расположены ещё и на host машине. Пишут, что это ужас-ужас с точки зрения безопасности, требуют всяких ключей типа:
cap_add:
— SYS_ADMIN
— DAC_READ_SEARCH
для работы команды mount в контейнере и прочая, и прочая.
В общем, когда в очередной раз после выгрузки контейнеров на сервер заказчика сервисы перестали видеть сетевые диски, я не особо удивился. Так уже бывало, и даже была написана пошаговая инструкция для группы поддержки, как и что перезагружать, когда ломаются сетевые настройки докера.
Так что я открываю свою инструкцию и начинаю действовать. Перезапускаю контейнеры — не помогает. Перезапускаю через docker-compose с пересозданием инфраструктуры — не помогает. Сбрасываю настройки Docker к заводским, восстанавливаю параметры виртуалки, загружаю заново образы, запускаю через docker-compose — опять всё по старому — не видит сеть. Точнее не подключается к сетевым шарам, хотя пинг из контейнера до SMB сервера проходит нормально. Последний пункт — перезагрузку сервера и переустановку Docker, пока пропускаю, так как перезагружать сервер очень не хочется. На этом инструкция кончилась.
Ок, перехожу на свою домашнюю машину, тут у меня тоже Docker под Windows, но чуть более новой версии. Проверяю на нём. Те же яйца:
Ага. Ну неужели, думаю, Docker накатил обновление с какой-то безопасностью и теперь мои скрипты из-за этого не запускаются? Последняя проверка — начисто удалить Docker с машины, и поставить заново. Это должно быть круче сброса к заводским настройкам. Проделываю весь перечень из предыдущего шага, только в дополнение к этому ещё и перезагружаю свою машину, чтобы уж совсем железно. Ставлю Docker c нуля, заливаю образы, запускаю docker-compose — ёпрст! Все сервисы как не видели сетевых шар, так и продолжают писать при загрузке «mount error(22): Invalid argument»
Пробую запустить скрипт по строкам из командной строки: подключаюсь к контейнеру, запускаю по очереди команды и вижу, что всё подключается и работает как надо:
То есть, это что же, какая-то хрень с передачей параметров в скрипт при запуске контейнера?
Ищем ещё идеи. Все варианты с перезагрузкой докера отмели, остались варианты с возможными изменениями в родительском образе. У меня образ собирается на основе openjdk:8-jdk-alpine, конкретной версии не указано, так что какие-нибудь улучшения безопасности могли сломать мои скрипты. Может поменяли что-то в OpenJDK или дочернем Alpine?
Проверяю логи проекта, пробую выбрать более старые openjdk:8-jdk-alpine-3.8, openjdk:8-jdk-alpine-3.7 и т.д. — каждый раз пересобираю контейнер, проверяю — всё по-старому.
Чёрт подери! Может я что-то всё-таки поменял в своей сборке? Выгружаю из GIT’а версию проекта месячной давности, собираю — те же глюки. Трёхмесячной давности — проблема всё ещё тут. Как же так? Что изменилось? Конфигурация докера к настоящему моменту гарантировано рабочая, конфигурация образа — тоже не поменялась, исходники проекта те же самые (GIT всё сохраняет). Чудес не бывает — надо понять, где всё-таки появились изменения. В проде вручную запускаю команды подключения к шарам — так до перезапуска сервисы будут работать нормально и иду спать. Утро вечера мудренее.
Наутро приходит идея — что пора, видимо, узнать, а что собственно говоря не нравится скрипту при выполнении.
Сообщение «mount error(22): Invalid argument» — это не сильно информативно. Нахожу, что есть волшебный ключик -х для баша с которой он выводит отладочную инфу при выполнениии скриптов.
Начинаем отладку внутри sh:
И тут появляются какие-то непонятные моменты — строка начинается с кавычек, потом кавычки в конце… Откуда кавычки?
Идея — может запуск с помощью настоящего bash будет информативнее?
Инсталлирую в контейнер BASH:
Блин, тут вроде, когда строка начинается с плюса — это хорошо, но появились какие-то \r и параметры $’. ‘
Ставим Midnight Commander, чтобы уж экспериментировать с удобствами apk add mc и открываем скрипт на редактирование, а там:
Оппа! ^M в конце каждой строки. Ну-ка, ну-ка, смотрим в локальном проекте — а что у нас с окончаниями строк. CRLF. Работаем под Windows, однако.
Меняем в этом конкретно файле CRLF на LF (да здравствует Notepad++!), собираем проект — бинго! Работает как надо.
Почему раньше было ок, а сейчас всё полетело? Смотрю по коммитам — не было никаких перемен. И тут вспоминаю, что GIT умеет на лету править символы перевода строк текстовых файлов. А я на днях подключил новый репозитарий, и возможно выгрузил оттуда все файлы с конвертацией в CRLF.
В итоге добавляем в проект файл .gitattributes, с указанием, что в отдельных файлах надо-таки сохранять символы конца строк как в UNIX:
Мораль — иногда виновник даже не попадает в круг первоначальных подозреваемых.
Постскриптум
DockerNAT has been removed from Docker Desktop 2.2.0.0 as using an IP address to communicate from the host to a container is not a supported feature. To communicate from a container to the host, you must use the special DNS name host.docker.internal.
Ок, поправил конфиги для тестового окружения, база данных подцепилась, пинг из контейнера до host.docker.internal проходит, а вот сетевые диски не подключаются. Пробую запустить mount вручную из шелла, и получаю знакомую ошибку «mount error(22): Invalid argument».
Убираю по очереди аргументы — запускаю просто «mount -t cifs //host.docker.internal/playground /pipeline» — вроде работает, но стучится от пользователя «root».
Добавляю пользователя: mount -t cifs //host.docker.internal/playground /pipeline -o user=smbuser — спрашивает пароль и подключается!
Полный вариант тоже работает:
а вот «mount -t cifs //host.docker.internal/playground /pipeline -o user=smbuser,password=smbpassword,vers=2.0» не пашет.
Меняю последний параметр на vers=2.1 — ура, работает!
Похоже, что Docker в последней версии сделал свою собственную имплементацию SMB сервера с блекджеком, но без поддержки 2.0. Ерунда, конечно, по сравнению с другими новостями.
Источник
Dockerfile and Docker run -w / workdir
Let’s take the sample python dockerfile as an example.
and then the run command to run the tests with in that container:
docker run —rm -v$(CWD):/project -w/project mydocker:1.0 pytest tests/
We are declaring the WORKDIR in the dockerfile and the run.
Am I right in saying
The WORKDIR in the dockerfile is the directory which the subsequent commands in the Dockerfile are run? But this will have no impact on when we run the docker run command?
Instead we need to pas in the -w/project to have pytests run in the /projects directory, well for pytest to look for the rests directory in /projects.
1 Answer 1
In the example you give, you shouldn’t need either the -v or -w option.
Various options in the Dockerfile give defaults that can be overridden at docker run time. CMD in the Dockerfile, for example, will be overridden by anything in a docker run command after the image name. (. and it’s better to specify it in the Dockerfile than to have to manually specify it on every docker run invocation.)
Specifically to your question, WORKDIR affects the current directory for subsequent RUN and COPY commands, but it also specifies the default directory when the container runs; if you don’t have a docker run -w option it will use that WORKDIR . Specifying -w to the same directory as the final image WORKDIR won’t have an effect.
You also COPY the code into your image in the Dockerfile (which is good). You don’t need a docker run -v option to overwrite that code at run time.
More specifically looking at pytest, it won’t usually write things out to the filesystem. If you are using functionality like JUnit XML or code coverage reports, you can set it to write those out somewhere other than your application directory:
Источник
Docker WORKDIR path добавляется к относительному пути
У меня проблема с тем, что следующий DOCKERFILE заканчивается в исключении, где он не может найти /src/webui/tail -f /dev/null , и это правильно, потому что я хотел выполнить только tail -f /dev/null .
Сборка докера работает , запуск докера не выполнен !
Как я могу избежать добавления пути WORKDIR в команду tail?
Исключение :
Системная информация .
- Docker Desktop (Windows 10 Pro)
- Докер версия 19.03.8, сборка afacb8b
3 ответа
Когда вы задаете CMD (или RUN или ENTRYPOINT ) в форме массива JSON, вы отвечаете за ручное разбиение команды на «слова». То есть вы запускаете эквивалент команды в кавычках оболочки
И все это интерпретируется как одно «слово» — пробелы и опции взяты как часть имени команды для поиска в $PATH .
Самый простой способ обойти это — удалить цитату и просто использовать пустую строку как CMD .
Обратите внимание, что контейнер, который вы создаете, на самом деле ничего не делает: он не содержит никакого исходного кода приложения, а команда, которую вы намеренно предоставляете, ничего не делает вечно. Помимо одного запущенного контейнера с бездействующим процессом, вы получите тот же эффект, просто не запустив контейнер вообще. Обычно вы хотите скопировать код своего приложения и установить CMD для его фактического запуска:
CMD добавится после ENTRYPOINT
Поскольку узел: 12.17.0-alpine имеет значение по умолчанию ENTRYPONINT node
Ваш докер-файл будет
Опция 1
Переопределить ENTRYPOINT во время сборки
Option2
Переопределить ENTRYPOINT во время выполнения
Так что разница в том, что это:
Подробнее о CMD вы можете прочитать в официальных документах Docker в документах.
Источник
What is the point of WORKDIR on Dockerfile?
I’m learning Docker. For many times I’ve seen that Dockerfile has WORKDIR command:
Can’t I just omit WORKDIR and Copy and just have my Dockerfile at the root of my project? What are the downsides of using this approach?
6 Answers 6
The WORKDIR instruction sets the working directory for any RUN, CMD, ENTRYPOINT, COPY and ADD instructions that follow it in the Dockerfile. If the WORKDIR doesn’t exist, it will be created even if it’s not used in any subsequent Dockerfile instruction.
Also, in the Docker best practices it recommends you to use it:
. you should use WORKDIR instead of proliferating instructions like RUN cd … && do-something, which are hard to read, troubleshoot, and maintain.
I would suggest to keep it.
I think you can refactor your Dockerfile to something like:
You dont have to
RUN mkdir -p /usr/src/app
This will be created automatically when you specifiy your WORKDIR
You can think of WORKDIR like a cd inside the container (it affects commands that come later in the Dockerfile, like the RUN command). If you removed WORKDIR in your example above, RUN npm install wouldn’t work because you would not be in the /usr/src/app directory inside your container.
I don’t see how this would be related to where you put your Dockerfile (since your Dockerfile location on the host machine has nothing to do with the pwd inside the container). You can put the Dockerfile wherever you’d like in your project. However, the first argument to COPY is a relative path, so if you move your Dockerfile you may need to update those COPY commands.
Источник