簡體   English   中英

Docker 不在指定卷中創建文件

[英]Docker doesn't create files in specified volume

我創建了這個小演示程序來顯示我遇到的問題。

public class DemoApplication {

public static void main(String[] args) {
    create(".", "1");
    create("", "2");
    create("app/usr", "3");
    create("/usr/app", "4");
    create("usr/app", "5");
}

public static void create(String location, String name) {
    try {
        File myObj = new File(location+ "/" + name + ".txt");
        if (myObj.createNewFile()) {
            System.out.println("File created: " + myObj.getName());
        } else {
            System.out.println("File already exists.");
        }
    } catch (IOException e) {
        System.out.println("An error occurred.");
        e.printStackTrace();
    }
}

}

我正在使用這個 Dockerfile

FROM openjdk:8-jdk-alpine
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} /usr/app/demo.jar
WORKDIR /usr/app/
VOLUME /usr/app/
ENTRYPOINT ["java","-jar","demo.jar"]

這些命令來構建容器

mvn clean package
docker build -t please/work .

最后但並非最不重要的是這個命令來運行容器

docker run please/work -v /root/hayasaka:/usr/app/

我也試過用這個

docker run please/work -v /root/hayasaka:/

但在這兩種情況下,都不會在 /root/hayasaka 創建文件

這是我在運行容器時得到的控制台 output

File created: 1.txt
File created: 2.txt
An error occurred.
java.io.IOException: No such file or directory
        at java.io.UnixFileSystem.createFileExclusively(Native Method)
        at java.io.File.createNewFile(File.java:1012)
        at com.example.demo.DemoApplication.create(DemoApplication.java:23)
        at com.example.demo.DemoApplication.main(DemoApplication.java:15)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:109)
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
File created: 4.txt
An error occurred.
java.io.IOException: No such file or directory
        at java.io.UnixFileSystem.createFileExclusively(Native Method)
        at java.io.File.createNewFile(File.java:1012)
        at com.example.demo.DemoApplication.create(DemoApplication.java:23)
        at com.example.demo.DemoApplication.main(DemoApplication.java:17)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:109)
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)

理論上應該在指定卷中創建1.txt或2.txt。 哦,我也使用 Spring 初始化程序創建了項目,因為實際項目也是使用該工具創建的。 作為可選依賴項,我只選擇了開發工具,我沒有更改 pom.xml 文件中的任何內容。

編輯:為了使這個答案完整,我添加了在對該問題的評論中已經提到的內容。 docker run命令上的-v開關位置不正確的事實。

您的執行在此處未按預期運行的首要原因是-v /some/path開關附加到docker run命令的末尾,位於映像名稱之后。

docker run --help生成以下輸入語法描述:

Usage:  docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

這里聲明必須在圖像名稱之前提供[OPTIONS] 所有選項開關都以單或雙-開頭,並且在大多數情況下,后跟開關的參數。 因此docker二進制文件將識別docker run命令的第一個參數,該參數前面沒有-作為圖像的名稱。

Arguments 跟隨圖像名稱,將被解釋為覆蓋命令( [COMMAND] [ARG...] ),並附加到構建圖像的ENTRYPOINT中定義的Dockerfile

您已經定義了ENTRYPOINT

ENTRYPOINT ["java","-jar","demo.jar"]

鑒於您提供的第一個示例執行是這樣的:

docker run please/work -v /root/hayasaka:/usr/app/

在容器中執行的結果命令將是這樣的:

java -jar demo.jar -v /root/hayasaka:/usr/app/

這當然不是你的本意。 如果程序可能不期望任何 arguments,它會簡單地忽略它們。

以下是您的輸入和結果的概述。

文件1.txt

    create(".", "1");

這將成為./1.txt ,或絕對意義上的/usr/app/1.txt ,這是一條很好且有效的路徑。 文件1.txt會在java進程的工作目錄下創建,該目錄又是啟動java程序的用戶的工作目錄,你在Dockerfile中設置為/usr/app usrF8652。

文件2.txt

    create("", "2");

這將創建文件/2.txt ,這是容器中文件系統根目錄中的一個文件。 鑒於只有目錄/usr/app是卷映射的,因此從容器外部看不到該文件。

文件3.txt

    create("app/usr", "3");

這將創建文件app/usr/3.txt ,這是一個相對於 java 進程的工作目錄的位置。 絕對路徑是/usr/app/app/usr/3.txt 這失敗了,很可能是由於缺少中間目錄結構app/usr 使用此方法解決問題:

    if (!myObj.getParentFile().exists()) {
        myObj.getParentFile().mkdirs();

這將創建缺少的中間目錄。

文件4.txt

    create("/usr/app", "4");

這將創建文件/usr/app/4.txt ,這是一個存在的絕對路徑,因為 docker 構建將使用給定的Dockerfile定義創建它。 這里沒有問題。

文件5.txt

    create("usr/app", "5")

這會嘗試創建文件usr/app/5.txt ,與文件3.txt一樣,它是相對於 java 進程的工作目錄的位置。 絕對路徑為/usr/app/usr/app/5.txt會失敗,原因與3.txt失敗的原因相同。

我希望這提供了一個很好的概述!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM