skaffold 会为某些文件重建映像,而不会为其他文件重建映像

skaffold rebuilds image for some files and doesn't for others

我试图理解为什么有时我在我的项目中更新 .php 它每次都完全重建图像,而其他时候它似乎什么也没做。实际上关于后者,它说 Syncing 1 files for ...,但反映了我的 none 更改。

这是我的项目结构:

/app
  /admin
    /conf
      app.conf
    /src
      /lib
        lib.php
      index.php
    Dockerfile.dev
  /manifests
    /dev
      ingress.yaml
      admin.yaml
  skaffold.yaml

当我对 ./admin/conf/app.conf./admin/src/index.php 进行更改时,我只得到 Syncing 1 files for...,但 none 的更改会反映在应用程序中。我必须 CTRL+C 杀死 Skaffold 并重新启动它...只需 CTRL+S.yamllib.php 中触发重建。

当我对 ./admin/src/lib/lib.php 进行更改时,它会从头开始重建整个图像。

这是我的配置:

# skaffold.yaml

apiVersion: skaffold/v1beta15
kind: Config
build:
  local:
    push: false
  artifacts:
    - image: postgres
      context: postgres
      docker:
        dockerfile: Dockerfile.dev
      sync:
        manual:
          - src: "***/*.sql"
            dest: .
    - image: testappacr.azurecr.io/test-app-admin
      context: admin
      docker:
        dockerfile: Dockerfile.dev
      sync:
        manual:
          - src: "***/*.php"
            dest: .
          - src: "***/*.conf"
            dest: .
          - src: "***/*.tbs"
            dest: .
          - src: "***/*.css"
            dest: .
          - src: "***/*.js"
            dest: .
deploy:
  kubectl:
    manifests:
      - manifests/dev/ingress.yaml 
      - manifests/dev/postgres.yaml
      - manifests/dev/admin.yaml
# Dockerfile.dev

FROM php:7.3-fpm
EXPOSE 4000
COPY . /app
WORKDIR /app/src
RUN apt-get update \ 
    && apt-get install -y libpq-dev zlib1g-dev libzip-dev \
    && docker-php-ext-install pgsql zip
CMD ["php", "-S", "0.0.0.0:4000"]
apiVersion: apps/v1
kind: Deployment
metadata:
  name: admin-deployment-dev
spec:
  replicas: 1
  selector:
    matchLabels:
      component: admin
  template:
    metadata:
      labels:
        component: admin
    spec:
      containers:
        - name: admin
          image: testappacr.azurecr.io/test-app-admin
          ports:
            - containerPort: 4000
          env:
            - name: PGUSER
              valueFrom:
                secretKeyRef:
                  name: test-app-dev-secrets
                  key: PGUSER
            - name: PGHOST
              value: postgres-cluster-ip-service-dev
            - name: PGPORT
              value: "1423"
            - name: PGDATABASE
              valueFrom:
                secretKeyRef:
                  name: test-app-dev-secrets
                  key: PGDATABASE
            - name: PGPASSWORD
              valueFrom:
                secretKeyRef:
                  name: test-app-dev-secrets
                  key: PGPASSWORD
            - name: SECRET_KEY
              valueFrom:
                secretKeyRef:
                  name: test-app-dev-secrets
                  key: SECRET_KEY
            - name: SENDGRID_API_KEY
              valueFrom:
                secretKeyRef:
                  name: test-app-dev-secrets
                  key: SENDGRID_API_KEY
            - name: DOMAIN
              valueFrom:
                secretKeyRef:
                  name: test-app-dev-secrets
                  key: DOMAIN           
            - name: DEBUG
              valueFrom:
                secretKeyRef:
                  name: test-app-dev-secrets
                  key: DEBUG
          # livenessProbe:
          #   tcpSocket:
          #     port: 4000
          #   initialDelaySeconds: 2
          #   periodSeconds: 2
          # readinessProbe:
          #   tcpSocket:
          #     port: 4000
          #   initialDelaySeconds: 2
          #   periodSeconds: 2
          volumeMounts:
          - mountPath: "/docs/"
            name: file-storage
      volumes:
        - name: file-storage
          persistentVolumeClaim:
            claimName: file-storage
---
apiVersion: v1
kind: Service
metadata:
  name: admin-cluster-ip-service-dev
spec:
  type: ClusterIP
  selector:
    component: admin
  ports:
    - port: 4000
      targetPort: 4000

我想我想了解一些事情:

  1. 为什么在一种情况下会触发完全重建?
  2. 为什么文件是 "Synced",但在我触发重建之前更改不会反映出来?
  3. 如何在不触发完全重建的情况下让我的更改反映在应用程序中?

谢谢!

对于第一个问题,建议更改 Dockerfile 中的命令顺序,以便有效地进行缓存。

# Dockerfile.dev

FROM php:7.3-fpm
EXPOSE 4000
RUN apt-get update \ 
    && apt-get install -y libpq-dev zlib1g-dev libzip-dev \
    && docker-php-ext-install pgsql zip
COPY . /app
WORKDIR /app/src
CMD ["php", "-S", "0.0.0.0:4000"]

对于第 2 和第 3 个问题,请运行以下命令启动 skaffold。

skaffold dev --trigger polling

所以有几个问题。首先,您的通配符应该是 ** 而不是 ***。 Skaffold 使用的 globbing 库无法识别 ***,因此它将其视为路径名的文字部分。由于您没有字面上命名为 *** 的目录,因此没有匹配的同步规则,因此您的文件更改会导致映像被重建。

当我更正通配符时,您的设置仍然不适合我。

首先,我在修改 index.php:

时看到警告
Syncing 1 files for testappacr.azurecr.io/test-app-admin:4c76dec58e1ef426b89fd44e3b340810db96b6961c5cacfdb76f62c9dc6725b8
WARN[0043] Skipping deploy due to sync error: copying files: didn't sync any files

默认情况下,Skaffold 会在警告级别切断日志。如果我改为 运行 skaffold dev -v info 我会得到更多信息:

INFO[0011] files modified: [admin/src/index.php]        
Syncing 1 files for testappacr.azurecr.io/test-app-admin:4c76dec58e1ef426b89fd44e3b340810db96b6961c5cacfdb76f62c9dc6725b8
INFO[0011] Copying files: map[admin/src/index.php:[/app/src/src/index.php]] to testappacr.azurecr.io/test-app-admin:4c76dec58e1ef426b89fd44e3b340810db96b6961c5cacfdb76f62c9dc6725b8 
WARN[0011] Skipping deploy due to sync error: copying files: didn't sync any files 

注意报告的目的地,/app/src/src/index.php。当您的图像 WORKDIR 设置为 /app/src 并且您的 PHP 同步规则保留了 app/admin 下的路径时,就会出现这个双重 src。您可以通过修改 skaffold.yaml 去除前导 src:

来解决此问题
      - src: "src/**/*.php"
        dest: .
        strip: src

您可能还需要调整其他规则,请注意您可以在规则中使用 dest: ..

(旁注:我仍然看到 didn't sync any files 错误。我实际上是 运行ning skaffold dev --status-check=false 以防止 Skaffold 等待部署状态——我认为部署永远不会成功,因为我没有任何有效的 PHP 文件。但事实证明部署实际上失败了,因为我没有可用的持久卷声明,因此 pod 无法启动。自从那里没有 运行ning 容器,文件从未同步过,因此 Skaffold 报告同步失败。所以这个故事的寓意是文件同步仅适用于 运行ning 容器。)