Когда я запускаю свое приложение в контейнере Docker, пути к файлам портятся

public File convert(MultipartFile multipartFile) {
        byte[] bytes;
       try {
           bytes = multipartFile.getBytes();
           try (FileOutputStream fos = new FileOutputStream("files/" + multipartFile.getOriginalFilename())) {
               fos.write(bytes);
           }
       } catch(IOException e) {
           System.out.println("Exception when converting multipart file to array of bytes");
           System.out.println(e.getCause());
           System.out.println(e.getMessage());
       }
        return new File("files/" + multipartFile.getOriginalFilename());
    }

У меня есть этот метод, который преобразует MultipartFile в файл (из пакета .io). files/ — это каталог внутри базового каталога моего проекта. На моем локальном компьютере все работает нормально (ubuntu 22), но когда я запускаю приложение в контейнере докеров и вызываю этот метод, он выдает IOException:

file-exchange-web-1       | Exception when converting multipart file to array of bytes
file-exchange-web-1       | null
file-exchange-web-1       | files/zip.png (No such file or directory)

Вот что происходит, когда я пытаюсь получить доступ к этому файлу:

file-exchange-web-1       | java.io.FileNotFoundException: file [/apps/files/zip.png] cannot be resolved in the file system for checking its content length

Вот мой докер-файл:

FROM openjdk:21-slim

WORKDIR /apps
ARG JAR_FILE
COPY target/${JAR_FILE} /apps/app.jar
COPY /entrypoint.sh /apps/entrypoint.sh

RUN adduser --system servuser
RUN chmod +x /apps/entrypoint.sh
RUN chown -R servuser /apps

USER servuser
EXPOSE 8080 8080
CMD ["/apps/entrypoint.sh"]

Я понимаю, что dockerfile меняет рабочий каталог на /apps и меняет путь, но я не совсем понимаю, что именно делает WORKDIR: где он создает каталог /apps, в каком каталоге в контейнере находится мое приложение и т. д. Я также слышал об использовании System.getProperty("user.dir"); но я не совсем понимаю, где в контейнере находится мое приложение, поэтому для меня это не имеет особого смысла. Я погуглил концепцию точных каталогов, которая помещает приложение в контейнер, но не нашел ничего, что могло бы мне помочь.

Отредактировано*

Изменение файла Docker решило мою проблему:

ОТ openjdk:21-slim

РАБОЧИЙ ПАРАМЕТР/приложения ARG JAR_FILE КОПИРОВАТЬ target/${JAR_FILE} /apps/app.jar КОПИРУЙТЕ /entrypoint.sh /apps/entrypoint.sh.

RUN adduser --системный серверный пользователь ЗАПУСК chmod +x /apps/entrypoint.sh ЗАПУСТИТЬ chown -R сервер/приложения ЗАПУСК файлов mkdir

Пользователь root РАЗВЕРНУТЬ 8080 8080 CMD ["/apps/entrypoint.sh"]

Я думаю, что WORKDIR предназначен только для того, чтобы использовать файл Docker. Вы можете определить путь, распечатав текущий каталог, например new File(".")

NawaMan 13.07.2024 22:44

Я предполагаю, что проблема в том, что каталог файлов не существует в контейнере Docker.

Tim Moore 14.07.2024 01:08

Вы были правы, я забыл это создать. Спасибо :)

Onurjan 14.07.2024 11:46
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
3
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Вы устанавливаете WORKDIR при создании образа докера, и это гарантирует, что все команды RUN используют один и тот же путь. Должен быть создан файл под корнем, т. е. /apps, но когда вы действительно запускаете образ докера, вам также необходимо указать /apps как ваш рабочий каталог, используя опцию -w.
Способ устранения таких проблем: docker run -it --entrypoint=/bin/bash и вы можете посмотреть структуру каталогов вашего изображения и то, что там существует.

Большое спасибо, я понял, что проблема в том, что я не создал каталог файлов в apps/. Я добавил эти две команды RUN mkdir files USER root, и теперь у меня все работает нормально.

Onurjan 14.07.2024 11:47
docker run -w и WORKDIR оба устанавливают одно и то же: текущий каталог в контейнере. IME нужен довольно редко docker run -w.
David Maze 14.07.2024 12:51

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