<p>I am testing automation by applying Gitlab CI/CD to a GKE cluster. The app is successfully deployed, but the source code changes are not applied (eg renaming the html title).</p>
<p>I have confirmed that the code has been changed in the gitlab repository master branch. No other branch.</p>
<p>CI/CD simply goes through the process below.</p>
<ol>
<li>push code to master branch</li>
<li>builds the NextJS code</li>
<li>builds the docker image and pushes it to GCR</li>
<li>pulls the docker image and deploys it in.</li>
</ol>
<p>The content of the menifest file is as follows.</p>
<p>.gitlab-ci.yml</p>
<pre><code>stages:
  - build-push
  - deploy

image: docker:19.03.12
variables:
  GCP_PROJECT_ID: PROJECT_ID..
  GKE_CLUSTER_NAME: cicd-micro-cluster
  GKE_CLUSTER_ZONE: asia-northeast1-b
  DOCKER_HOST: tcp://docker:2375/
  DOCKER_TLS_CERTDIR: &quot;&quot;
  REGISTRY_HOSTNAME: gcr.io/${GCP_PROJECT_ID}
  DOCKER_IMAGE_NAME: ${CI_PROJECT_NAME}
  DOCKER_IMAGE_TAG: latest
services:
  - docker:19.03.12-dind

build-push:
 stage: build-push
 before_script:
   - docker info
   - echo &quot;$GKE_ACCESS_KEY&quot; &gt; key.json
   - docker login -u _json_key --password-stdin https://gcr.io &lt; key.json
 script:
   - docker build --tag $REGISTRY_HOSTNAME/$DOCKER_IMAGE_NAME:$DOCKER_IMAGE_TAG .
   - docker push $REGISTRY_HOSTNAME/$DOCKER_IMAGE_NAME:$DOCKER_IMAGE_TAG

deploy:
  stage: deploy
  image: google/cloud-sdk
  script:
    - export USE_GKE_GCLOUD_AUTH_PLUGIN=True
    - echo &quot;$GKE_ACCESS_KEY&quot; &gt; key.json
    - gcloud auth activate-service-account --key-file=key.json
    - gcloud config set project $GCP_PROJECT_ID
    - gcloud config set container/cluster $GKE_CLUSTER_NAME
    - gcloud config set compute/zone $GKE_CLUSTER_ZONE
    - gcloud container clusters get-credentials $GKE_CLUSTER_NAME --zone $GKE_CLUSTER_ZONE --project $GCP_PROJECT_ID
    - kubectl apply -f deployment.yaml
    - gcloud container images list-tags gcr.io/$GCP_PROJECT_ID/${CI_PROJECT_NAME} --filter='-tags:*' --format=&quot;get(digest)&quot; --limit=10 &gt; tags &amp;&amp; while read p; do gcloud container images delete &quot;gcr.io/$GCP_PROJECT_ID/${CI_PROJECT_NAME}@$p&quot; --quiet; done &lt; tags
</code></pre>
<p>Dockerfile</p>
<pre><code># Install dependencies only when needed
FROM node:16-alpine AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app

# Install dependencies based on the preferred package manager
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
RUN \
  if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
  elif [ -f package-lock.json ]; then npm ci; \
  elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm &amp;&amp; pnpm i --frozen-lockfile; \
  else echo &quot;Lockfile not found.&quot; &amp;&amp; exit 1; \
  fi


# Rebuild the source code only when needed
FROM node:16-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .

# Next.js collects completely anonymous telemetry data about general usage.
# Learn more here: https://nextjs.org/telemetry
# Uncomment the following line in case you want to disable telemetry during the build.
# ENV NEXT_TELEMETRY_DISABLED 1

RUN yarn build

# If using npm comment out above and use below instead
# RUN npm run build

# Production image, copy all the files and run next
FROM node:16-alpine AS runner
WORKDIR /app

ENV NODE_ENV production
# Uncomment the following line in case you want to disable telemetry during runtime.
# ENV NEXT_TELEMETRY_DISABLED 1

RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

COPY --from=builder /app/public ./public

# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

USER nextjs

EXPOSE 3000

ENV PORT 3000

CMD [&quot;node&quot;, &quot;server.js&quot;]
</code></pre>
<p>deployment.yaml</p>
<pre><code>apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontweb-lesson-prod
  labels:
    app: frontweb-lesson
spec:
  selector:
    matchLabels:
      app: frontweb-lesson
  template:
    metadata:
      labels:
        app: frontweb-lesson
    spec:
      containers:
      - name: frontweb-lesson-prod-app
        image: gcr.io/PROJECT_ID../REPOSITORY_NAME..:latest
        ports:
        - containerPort: 3000
        resources:
          requests:
            cpu: 200m
---
apiVersion: v1
kind: Service
metadata:
  name: frontweb-lesson-prod-svc
  labels:
    app: frontweb-lesson
spec:
  selector:
    app: frontweb-lesson
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 3000
  type: LoadBalancer
  loadBalancerIP: &quot;EXTERNAL_IP..&quot;
</code></pre>
<p>Is there something I'm missing?</p>

<p>By default,<strong>imagepullpolicy</strong> will be <strong>Always</strong> but there could be chances if there is no change in the <strong>deployment</strong> file when applying it might not update the <strong>deployment</strong>. As you are using the same <strong>label</strong> each time <strong>latest</strong>.</p>
<p>As there different between <code>kubectl apply</code> and <code>kubectl patch</code> command</p>
<p>What you can do is add minor <strong>label</strong> change or <strong>annotation</strong> change in <strong>deployment</strong> and check image will get updated with <code>kubectl apply</code> command too otherwise it will be mostly <strong>unchange</strong> response of <code>kubectl apply</code></p>
<p>Ref : <a href="https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy" rel="nofollow noreferrer">imagepullpolicy</a></p>
<blockquote>
<p>You should avoid using the :latest tag when deploying containers in
production as it is harder to track which version of the image is
running and more difficult to roll back properly.</p>
</blockquote>
