简体   繁体   English

使用 ggsave() 和 Docker 生成一个 png 文件

[英]Generating a png file using ggsave() and Docker

As a first attempt at Docker, I am trying to run some R code to generate a PNG file from a Docker container.作为 Docker 的第一次尝试,我尝试运行一些 R 代码以从 Docker 容器生成 PNG 文件。 I am using WSL 2 with Windows 11 and am only using the Docker CLI, not Docker Desktop.我将 WSL 2 与 Windows 11 一起使用,并且仅使用 Docker CLI,而不是 Docker 桌面。

Dockerfile Dockerfile

FROM r-base

# Modify the date at build time
ARG WHEN

# Execute R from the terminal
RUN R -e "options(repos =  \
   list(CRAN = 'http:/mran.revolutionanalytics.com/snapshot/${WHEN}')); \
   install.packages('ggplot2')"

# Create a path in the container
RUN mkdir -p /home/
RUN mkdir /home/code
RUN mkdir /home/results

# Copy the file to a path in the container
COPY ./Code/iris.R /home/code/iris.R

WORKDIR /home/code

# Run iris.R in the container
CMD ["Rscript", "iris.R"]

# Copy iris.png
COPY ./iris.png /home/results/iris.png

Code/iris.R代码/iris.R

library(ggplot2)

p <- ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width,
                 color = Species)) +
  geom_point() +
  geom_smooth(method = "lm") +
  theme_bw() +
  theme(panel.grid = element_blank()) +
  xlab("Sepal Length") +
  ylab("Sepal Width") +
  scale_x_continuous(limits = c(4, 8), breaks = seq(4, 8, 0.5)) +
  scale_y_continuous(limits = c(2, 5), breaks = 2:5)

ggsave(filename = file.path(getwd(), "iris.png"), plot = p, device = "png")

Replicating the problem in Docker CLI在 Docker CLI 中复制问题

$ docker build --build-arg WHEN=2022-12-10 -t plot .
Sending build context to Docker daemon  4.608kB
Step 1/10 : FROM r-base
 ---> 3de1ef2039fb
Step 2/10 : ARG WHEN
 ---> Using cache
 ---> ff24cab2714d
Step 3/10 : RUN R -e "options(repos =     list(CRAN = 'http:/mran.revolutionanalytics.com/snapshot/${WHEN}'));    install.packages('ggplot2')"
 ---> Using cache
 ---> 67b96e10f028
Step 4/10 : RUN mkdir -p /home/
 ---> Using cache
 ---> 65e100a0ca92
Step 5/10 : RUN mkdir /home/code
 ---> Using cache
 ---> 08506b7b2d44
Step 6/10 : RUN mkdir /home/results
 ---> Using cache
 ---> 149966cff268
Step 7/10 : COPY ./Code/iris.R /home/code/iris.R
 ---> Using cache
 ---> 5bba4c93e928
Step 8/10 : WORKDIR /home/code
 ---> Using cache
 ---> 1b5a8b7ee36b
Step 9/10 : CMD ["Rscript", "iris.R"]
 ---> Using cache
 ---> 8c9cc56e90f4
Step 10/10 : COPY ./iris.png /home/results/iris.png
COPY failed: file not found in build context or excluded by .dockerignore: stat iris.png: file does not exist

I have also tried commenting out the last CMD line and the last COPY line and running Rscript iris.R myself.我还尝试注释掉最后CMD行和最后一个COPY行并自己运行Rscript iris.R

$ docker build --build-arg WHEN=2022-12-10 -t plot .
Sending build context to Docker daemon  4.608kB
Step 1/8 : FROM r-base
 ---> 3de1ef2039fb
Step 2/8 : ARG WHEN
 ---> Using cache
 ---> ff24cab2714d
Step 3/8 : RUN R -e "options(repos =     list(CRAN = 'http:/mran.revolutionanalytics.com/snapshot/${WHEN}'));    install.packages('ggplot2')"
 ---> Using cache
 ---> 67b96e10f028
Step 4/8 : RUN mkdir -p /home/
 ---> Using cache
 ---> 65e100a0ca92
Step 5/8 : RUN mkdir /home/code
 ---> Using cache
 ---> 08506b7b2d44
Step 6/8 : RUN mkdir /home/results
 ---> Using cache
 ---> 149966cff268
Step 7/8 : COPY ./Code/iris.R /home/code/iris.R
 ---> Using cache
 ---> 5bba4c93e928
Step 8/8 : WORKDIR /home/code
 ---> Using cache
 ---> 1b5a8b7ee36b
Successfully built 1b5a8b7ee36b
Successfully tagged plot:latest
$ docker run -d plot tail -f /dev/null
dd2395f02f9793f1f4fca53eab904c33f38e9ee0dd3b14bcbdd56cd96693e150
$ docker exec -it dd2395f02f97 bash
root@dd2395f02f97:/home/code# ls
iris.R
root@dd2395f02f97:/home/code# Rscript iris.R
Saving 7 x 7 in image
`geom_smooth()` using formula = 'y ~ x'
root@dd2395f02f97:/home/code# ls
iris.png  iris.R

and here it appears, but it does NOT appear when I try to automate this, as described above.它出现在这里,但是当我尝试自动化时它没有出现,如上所述。

I also tried adding --no-cache and this did not fix the issue.我还尝试添加--no-cache但这并没有解决问题。 It is not clear to me whether the issue is with ggsave() or with Docker.我不清楚问题出在ggsave()还是 Docker。

I figured out a solution to the problem, thanks to MrFlick's comment.感谢 MrFlick 的评论,我找到了解决问题的方法。

The key thing to understand here is that output needs to be stored outside of the container on a local drive.这里要理解的关键是 output 需要存储在容器外的本地驱动器上。 It is also important to understand that the current directory .了解当前目录也很重要. referenced in any statements in the MakeFile will refer to the mounted directory.在 MakeFile 中的任何语句中引用的将引用挂载的目录。

Dockerfile Dockerfile

FROM r-base

# Set an environment variable
ENV MAINDIR /home

# Modify the date at build time
ARG WHEN

# Execute R from the terminal
RUN R -e "options(repos =  \
   list(CRAN = 'http:/mran.revolutionanalytics.com/snapshot/${WHEN}')); \
   install.packages('ggplot2')"

# Create a path in the container
RUN mkdir -p ${MAINDIR}

# Copy the file to a path in the container
COPY iris.R ${MAINDIR}

WORKDIR ${MAINDIR}

# Run iris.R in the container
CMD ["Rscript", "iris.R"]

Notably, the COPY iris.R statement will be looking for iris.R in the directory which will be mounted.值得注意的是, COPY iris.R语句将在将要挂载的目录中查找iris.R

[where you want the output]/iris.R [你想要输出的地方]/iris.R

library(ggplot2)

p <- ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width,
                 color = Species)) +
  geom_point() +
  geom_smooth(method = "lm") +
  theme_bw() +
  theme(panel.grid = element_blank()) +
  xlab("Sepal Length") +
  ylab("Sepal Width") +
  scale_x_continuous(limits = c(4, 8), breaks = seq(4, 8, 0.5)) +
  scale_y_continuous(limits = c(2, 5), breaks = 2:5)

ggsave(filename = "iris.png", plot = p, device = "png")

Docker CLI Docker 命令行界面

$ docker build --build-arg WHEN=2022-12-10 -t plot .
Sending build context to Docker daemon  70.14kB
Step 1/8 : FROM r-base
 ---> 3de1ef2039fb
Step 2/8 : ENV MAINDIR /home
 ---> Using cache
 ---> b8b3616ad975
Step 3/8 : ARG WHEN
 ---> Using cache
 ---> f5604ee4de70
Step 4/8 : RUN R -e "options(repos =     list(CRAN = 'http:/mran.revolutionanalytics.com/snapshot/${WHEN}'));    install.packages('ggplot2')"
 ---> Using cache
 ---> 8930de4d0a49
Step 5/8 : RUN mkdir -p ${MAINDIR}
 ---> Using cache
 ---> 5aa70002ed21
Step 6/8 : COPY /Code/iris.R ${MAINDIR}
 ---> 989fdac672b7
Step 7/8 : WORKDIR ${MAINDIR}
 ---> Running in 708bb8d8b42d
Removing intermediate container 708bb8d8b42d
 ---> 5edaa2e558a1
Step 8/8 : CMD ["Rscript", "iris.R"]
 ---> Running in 2d800c986828
Removing intermediate container 2d800c986828
 ---> dc23f821908a
Successfully built dc23f821908a
Successfully tagged plot:latest

and now for the key step:现在是关键步骤:

$ docker run -v [where you want the output]:/home/ plot
Saving 7 x 7 in image
`geom_smooth()` using formula = 'y ~ x'

Performing ls in that directory yields在该目录中执行ls会产生

$ ls
iris.R  iris.png

This can be generalized with more complicated folder structures as desired.这可以根据需要用更复杂的文件夹结构进行概括。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM