1

我有一个小型 Web 应用程序(一个名为 的 Rails 应用程序sofia),我在本地使用minikube.

当我创建 k8s 资源并运行我的部署时,容器不包含任何应该在映像构建过程中复制的文件。

这就是我正在做的事情:

Dockerfile

作为Dockerfile构建的一部分,我将本地克隆存储库的内容复制到映像工作目录中:

RUN mkdir -p /app
WORKDIR /app

COPY . ./

(旧)docker-compose设置

从历史上看,我使用一个docker-compose文件来运行这个应用程序及其所有服务。我将本地目录映射到容器的工作目录(见volumes:下文)。这在本地工作时非常方便,因为所有更改都反映在容器内“实时”:

# docker-compose.yml
sofia:
    build:
      context: .
      args:
        RAILS_ENV: development
    environment:
      DATABASE_URL: postgres://postgres:sekrit@postgres/
    image: sofia/sofia:local
    ports:
      - # ...
    volumes:
      - .:/app  #<---- HERE

构建k8s资源文件kompose

为了在上面运行它minikube,我使用 Kubernetes 自己提供的kompose工具将我的docker-compose文件转换为可以使用的 k8s 资源文件。

$ kompose convert --file docker-compose.yml --out k8s.yml --with-kompose-annotation=false
WARN Volume mount on the host "/Users/jeeves/git/jeeves/sofia" isn't supported - ignoring path on the host
INFO Kubernetes file "k8s.yml" created

如您所见,它会生成一条警告,提示我的本地卷无法安装到远程卷上。这是有道理的,因为 k8s 部署是“远程”运行的,所以我只是忽略了警告。

跑步

最后我用k8s/运行上面的资源minikube

minikube start
kubectl apply -f k8s.yml

我注意到sofia容器不断崩溃并重新启动,所以我检查了日志:

$ kubectl get pods
NAME                             READY   STATUS             RESTARTS   AGE
pod/sofia-6668945bc8-x9267       0/1     CrashLoopBackOff   1          10s
pod/postgres-fc84cbd4b-dqbrh     1/1     Running            0          10s
pod/redis-cbff75fbb-znv88        1/1     Running            0          10s

$ kubectl logs pod/sofia-6668945bc8-x9267
Could not locate Gemfile or .bundle/ directory

该错误是特定于 Ruby/Rails 的,但根本原因是容器中没有文件!我可以通过输入容器并检查文件来确认这一点ls- 它确实是空的。

问题

  1. 如果sofia/sofia:latest图像是使用COPY-ied 文件内容正确构建的,为什么在运行容器时它会消失minikube
  2. 我应该怎么做才能确保我的文件被正确复制?

谢谢!

4

1 回答 1

2

问题是卷在 docker-compose 和 K8s 中的 Docker 中的行为方式不同。Kompose 不能完美地翻译音量。在带有 docker-compose 的 Docker 中,您声明的卷保留目录中的现有文件,而在 k8s 中,卷被创建为空并隐藏现有内容。

没有直接等效的 docker-compose 卷可以将现有文件保存在 k8s 中,您必须使用以下选项之一解决这个问题,具体取决于您的用例中的意义:

  • 利用ConfigMaps将您的文件添加到此应用程序卷(如果需要,请使用 subPath)。如果容器启动时您的应用程序目录中存在少量配置文件,则可能没问题
  • 在你的dockerfile中,使用COPY到app-tmp之类的东西,然后在你的入口点脚本中将这些文件从那个app-tmp目录复制到你的“app”卷
  • 重构您的应用程序,使其将“app1”目录(无卷)与现有文件一起使用,“app2”开始为空并用作您的卷。
于 2021-11-23T21:08:28.463 回答