Как скопировать файл с хоста в контейнер при запуске?

Я пытаюсь создать образ докера с помощью файла докера, моя цель — скопировать файл в определенную папку, когда я запускаю команду «запуск докера»!

это мой код файла докеров:

    FROM openjdk:7

    MAINTAINER MyPerson

    WORKDIR /usr/src/myapp

    ENTRYPOINT ["cp"]

    CMD ["/usr/src/myapp"]

    CMD ls /usr/src/myapp

После создания моего образа без каких-либо ошибок (используя команду сборки docker) я попытался запустить свой новый образ:

    docker run myjavaimage MainClass.java

я получил эту ошибку: ** cp: отсутствует операнд файла назначения после «MainClass.java» **

Как я могу это решить? спасибо


person user1444393    schedule 12.11.2019    source источник
comment
ваша команда cp MainClass.java из-за ENTRYPOINT. что вы пытаетесь сделать с этим?   -  person LinPy    schedule 12.11.2019
comment
я пытаюсь скопировать файл MainClass.java с хоста в контейнер, когда он начинает работать (я хочу каждый раз указывать файл, который будет копироваться при каждой команде запуска докера)   -  person user1444393    schedule 12.11.2019
comment
это не сработает, вам нужно использовать тома или docker cp см. это, например, stackoverflow.com/questions/57771529/   -  person LinPy    schedule 12.11.2019
comment
Не думаю, что тома помогут (потому что моя цель — скопировать файл с хоста... а не наоборот)! ... и я не хочу вручную выполнять команду docker cp! ...   -  person user1444393    schedule 12.11.2019
comment
вы ошибаетесь, тома будут копировать файлы с вашего хоста в контейнер   -  person LinPy    schedule 12.11.2019
comment
@LinPy Я не уверен в этом. Я смонтировал хранилище файлов объемом 1 ТБ в свой док-контейнер (в котором по умолчанию нет места на 1 ТБ). Разве это не просто делает том (на хост-компьютере) доступным из контейнера, нет? Точно так же при использовании --privileged делает evth на хост-компьютере доступным.   -  person DUDANF    schedule 12.11.2019


Ответы (3)


Я думаю, вам нужен этот Dockerfile:

FROM openjdk:7
WORKDIR /usr/src/myapp
COPY MainClass.java .
RUN javac MainClass.java
ENV CLASSPATH=/usr/src/myapp
CMD java MainClass

Когда вы docker build создаете этот образ, он COPY загружает исходный файл Java из вашего локального каталога в образ, компилирует его и устанавливает некоторые метаданные, сообщающие JVM, где найти полученные .class файлы. Затем, когда вы запустите контейнер, он запустит единственное приложение, которое вы там упаковали.

Достаточно часто используется инструмент сборки более высокого уровня, такой как Maven или Gradle, для компиляции нескольких файлов в один файл .jar. Убедитесь, что COPY все исходные файлы вам нужны, прежде чем запускать сборку. В Java обычно создается файл .jar вне Docker и просто COPY без JDK, и это тоже разумный путь.

В показанном вами Dockerfile Docker объединяет ENTRYPOINT и CMD в одну команду и запускает эту команду как единственный основной процесс контейнера. Если вы предоставляете какую-либо команду в команде docker run, она переопределяет CMD, но не переопределяет ENTRYPOINT. Вы получаете только один ENTRYPOINT и один CMD, и последний в Dockerfile побеждает. Итак, вы пытаетесь запустить контейнерные процессы, например

# What's in the Dockerfile
cp /bin/sh -c "ls /usr/src/myapp"

# Via your docker run command
cp MainClass.java

Как предлагает @QuintenScheppermans в своем ответе, вы можете использовать параметр docker run -v для вставки файла во время выполнения, но это произойдет после того, как такие команды, как RUN javac, уже выполнены. На самом деле вам не нужен рабочий процесс, в котором все приложение перестраивается каждый раз, когда вы docker run используете контейнер. Создайте образ в течение docker build времени или раньше.

person David Maze    schedule 12.11.2019
comment
Спасибо за четкое объяснение, но я хотел бы сделать это автоматически, это означает, что я хочу передать имя файла (MainClass.java) в качестве аргумента в команде запуска докера... (не так: COPY MainClass. java . ) ... Надеюсь, вы меня поняли :) - person user1444393; 14.11.2019

Две вещи.

  1. Вы использовали CMD дважды.

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

FROM openjdk:
MAINTAINER MyPerson
WORKDIR /usr/src/
ENTRYPOINT ["cp"]
RUN /usr/src/myapp
RUN ls /usr/src/myapp
  1. Копирование материала в образ Существует простая команда COPY с синтаксисом COPY <from-here> <to-here>

Похоже, вы хотите запустить myjavaimage, так что вы сделаете следующее:

COPY /path/to/myjavaimage /myjavaimage
CMD myjavaimage MainClass.java

Там, где вы видите стрелки, я только что написал фиктивный код. Замените его правильным кодом.

Кроме того, ваш Dockerfile плохо создан.

ENTRYPOINT -> не знаю, зачем вам делать "cp" , но это фактическая точка входа. Может указывать на корневой каталог вашего проекта или на приложение, которое будет запущено. Не понимаю, почему вы хотите сделать ls /usr/src/myapp, но если хотите, используйте RUN, а не CMD.

Наконец, лучший способ отлаживать контейнеры докеров — в интерактивном режиме. Это означает, что вы подключитесь к контейнеру по ssh, осмотритесь, запустите код и посмотрите, в чем проблема.

Запустите это: docker run -it <image-name> /bin/bash, а затем загляните внутрь, и обычно это лучший способ увидеть, что вызывает проблемы.

person DUDANF    schedule 12.11.2019

Эта страница stackoverflow прекрасно отвечает на ваш вопрос.

COPY foo.txt /data/foo.txt
# where foo.txt is the relative path on host
# and /data/foo.txt is the absolute path in the image

Если вам нужно смонтировать файл при выполнении команды:

docker run --name=foo -d -v ~/foo.txt:/data/foo.txt -p 80:80 image_name
person Quinten Scheppermans    schedule 12.11.2019
comment
Я хочу каждый раз указывать файл, который будет копироваться при каждой команде запуска докера - person user1444393; 12.11.2019