我有一个小型web应用程序(一个名为sofia
的Rails应用程序(,我正在使用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
用kompose
构建k8s资源文件
为了在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
检查文件来确认这一点——它确实是空的。
问题
- 如果
sofia/sofia:latest
映像是用COPY
指定的文件内容正确构建的,为什么在minikube
上运行容器时会出现问题 - 我应该怎么做才能确保我的文件被正确复制
谢谢!
问题是,在Docker compose和K8s中,Volume在Docker中的行为方式不同。Kompose无法完美地转换音量。在Docker with Docker compose中,您声明的卷会保留目录中的现有文件,而在k8s中,一个卷会创建为空,并覆盖现有内容。
没有直接等效的docker compose卷可以将现有文件保存在k8s中,您必须使用以下选项之一来解决这个问题,这取决于您的用例中的意义:
- 利用ConfigMaps将您的文件添加到此应用程序卷(如果需要,请使用subPath(。如果容器启动时你的应用程序目录中有配置文件,那么对于一大堆配置文件来说可能还可以
- 在你的dockerfile中,使用COPY到类似于apptmp的东西,然后在你的入口点脚本中,将这些文件从apptmp目录复制到你的"应用程序";体积
- 重构您的应用程序,使其使用";app1";具有现有文件的目录(没有卷(;app2";开始时为空,并用作您的音量