[英]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.