Dockerfile go build command not getting cached in Github Actions - docker

I am using the Github Action actions/cache#v2 to cache the docker layers. Following is the build.yml file:
name: Build
on:
push:
branches:
- '**'
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout#v2
- name: Get Docker Tags
id: getDockerTag
run: |
echo ::set-output name=image_tag::${{github.sha}}
echo "Setting image tag as :: ${{github.sha}}"
# Set up buildx runner
- name: Set up Docker Buildx
uses: docker/setup-buildx-action#v1
- name: Cache Docker layers
uses: actions/cache#v2
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ hashFiles('**/Dockerfile') }}
restore-keys: |
${{ runner.os }}-buildx-
- name: Build docker image 1
uses: docker/build-push-action#v2
with:
push: false
tags: go-docker-caching:${{ steps.getDockerTag.outputs.image_tag }}
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache,mode=max
Dockerfile:
FROM golang:latest as builder
# create a working directory
WORKDIR /main
COPY go.mod go.sum ./
RUN ls -a
# Download dependencies
RUN go mod tidy
RUN go mod download
COPY . .
## Build binary
#RUN CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build -a -installsuffix cgo -ldflags="-w -s" -o gin_test
RUN go build -o main
# use a minimal alpine image for deployment
FROM alpine:latest
# add ca-certificates in case you need them
RUN apk update && apk add ca-certificates && rm -rf /var/cache/apk/*
# set working directory
WORKDIR /root
# copy the binary from builder
COPY --from=builder /main .
RUN touch .main.yml
# Specify the PORT
EXPOSE 8080:8080
# run the binary
CMD ["./main"]
On local, all docker commands are getting cached, but on Github Actions, the following commands are not getting cached which leads to the docker build taking around 3 minutes to download the modules, even if nothing is changed.
RUN go mod download
RUN go build -o main
How to make sure all the commands are cached?

Related

Question regarding configuration of Next JS on Cloud Run with Docker Images

I have a question regarding an approach and how secure it is. Basically I have a next js app which I push to Cloud Run via Github Actions. Now in Github Actions I have defined secrets which I then pass via github action yml file to Docker. Then in Docker I pass them to environment variables at build time. But then I use next.config.js to make it available to the app at build time. Here are my files
Github Action Yml File
name: nextjs-cloud-run
on:
push:
branches:
- main
env:
GCP_PROJECT_ID: ${{ secrets.GCP_PROJECT_ID }}
GCP_REGION: europe-west1
# project-name but it can be anything you want
REPO_NAME: some-repo-name
jobs:
build-and-deploy:
name: Setup, Build, and Deploy
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout#v2
# This step is where our service account will be authenticated
- uses: google-github-actions/setup-gcloud#v0.2.0
with:
project_id: ${{ secrets.GCP_PROJECT_ID }}
service_account_key: ${{ secrets.GCP_SA_KEYBASE64 }}
service_account_email: ${{ secrets.GCP_SA_EMAIL }}
- name: Enable the necessary APIs and enable docker auth
run: |-
gcloud services enable containerregistry.googleapis.com
gcloud services enable run.googleapis.com
gcloud --quiet auth configure-docker
- name: Build, tag image & push
uses: docker/build-push-action#v3
with:
push: true
tags: "gcr.io/${{ secrets.GCP_PROJECT_ID }}/collect-opinion-frontend:${{ github.sha }}"
secrets: |
"NEXT_PUBLIC_STRAPI_URL=${{ secrets.NEXT_PUBLIC_STRAPI_URL }}"
"NEXTAUTH_SECRET=${{ secrets.NEXTAUTH_SECRET }}"
"NEXTAUTH_URL=${{ secrets.NEXTAUTH_URL }}"
- name: Deploy Image
run: |-
gcloud components install beta --quiet
gcloud beta run deploy $REPO_NAME --image gcr.io/$GCP_PROJECT_ID/$REPO_NAME:$GITHUB_SHA \
--project $GCP_PROJECT_ID \
--platform managed \
--region $GCP_REGION \
--allow-unauthenticated \
--quiet
This is my Dockerfile for Next Js
# 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 && pnpm i --frozen-lockfile; \
else echo "Lockfile not found." && 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
# get the environment vars from secrets
RUN --mount=type=secret,id=NEXT_PUBLIC_STRAPI_URL \
--mount=type=secret,id=NEXTAUTH_SECRET \
--mount=type=secret,id=NEXTAUTH_URL \
export NEXT_PUBLIC_STRAPI_URL=$(cat /run/secrets/NEXT_PUBLIC_STRAPI_URL) && \
export NEXTAUTH_SECRET=$(cat /run/secrets/NEXTAUTH_SECRET) && \
export NEXTAUTH_URL=$(cat /run/secrets/NEXTAUTH_URL) && \
yarn build
# 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 ["node", "server.js"]
My next.config.js file
// next.config.js
module.exports = {
// ... rest of the configuration.
output: "standalone",
env: {
// Will only be available on the server side
NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET,
NEXTAUTH_URL: process.env.NEXTAUTH_URL, // Pass through env variables
},
};
My question is that, does this create a security issue with the fact that the environment variable could somehow be accessed via the client?
According to Next JS Documentation that should not be the case or at least that's how I understand. Snippet from the site
Note: environment variables specified in this way will always be included in the JavaScript bundle, prefixing the environment variable name with NEXT_PUBLIC_ only has an effect when specifying them through the environment or .env files.
I would appreciate if you could advise me on this

Github Actions Docker build: "/pmpn-lock.yaml" and "./nginx/default.conf" not found

So I'm having an issue with my docker build action with github actions and I definitely feel like the issue is obvious but I am failing to get it.
So here is my Github Action
name: Build / Publish
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build-and-push-docker-image:
name: Build Pinsel Docker image and push to repos
runs-on: ubuntu-latest
steps:
-
name: Checkout codebase
uses: actions/checkout#v2
-
name: Docker meta
id: meta
uses: docker/metadata-action#v3
with:
images: name/app
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
# Setup docker build
-
name: Set up Docker buildx
id: buildx
uses: docker/setup-buildx-action#v1
-
name: Login to Docker Hub
uses: docker/login-action#v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Login into Github Packages
uses: docker/login-action#v1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GHCR_PAT }}
-
name: Build image and push it to both registries
uses: docker/build-push-action#v2
with:
context: ../../
file: ./Dockerfile.prod
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
And here is my Dockerfile located in main directory
FROM node:16.4.2-alpine as build
RUN npm install -g pnpm#next-7
WORKDIR /app
ENV PATH /app/node_modules/.bin:$PATH
COPY /pnpm-lock.yaml ./
RUN pnpm fetch --prod
ADD . ./
RUN pnpm install -r --offline --prod
FROM nginx:1.21-alpine
COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
and lastly the error
#11 [build 5/8] COPY /package.json ./
#11 ERROR: failed to calculate checksum of ref ypf6stpm3t9h2xl6ezvwo7876::kvjk90tcw8wfykmdkvu1uvzgs: "/package.json": not found
#12 [stage-1 2/3] COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf
#12 CANCELED
Dockerfile.prod:13
--------------------
11 |
12 | FROM nginx:1.21-alpine
13 | >>> COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf
14 | COPY --from=build /app/build /usr/share/nginx/html
15 | EXPOSE 80
--------------------
error: failed to solve: failed to compute cache key: failed to calculate checksum of ref ypf6stpm3t9h2xl6ezvwo7876::kvjk90tcw8wfykmdkvu1uvzgs: "/nginx/default.conf": not found
Error: buildx failed with: error: failed to solve: failed to compute cache key: failed to calculate checksum of ref ypf6stpm3t9h2xl6ezvwo7876::kvjk90tcw8wfykmdkvu1uvzgs: "/nginx/default.conf": not found
Everything goes well on github actions until it needs to copy files. It says it can't find pnpm-lock.yaml, nor can it find ./nginx both of which are there.
I feel like the answer is super simple and I am just mentally fried and it's not standing out. If I can get a nudge in the right direction, it'd be appreciated!
I have realized that github/checkout puts you at the root directory of the github project, meaning I didn't need to add ../../ for context, I made the mistake of thinking I was navigating from the github action workflow directory.
So for anyone else who ends up this issue: actions/checkout will put you in the root directory of the repo, so you only need to use navigate via context if your dockerfiles are somewhere other than the root folder (like in their own docker folder)

COPY failed: no source files were specified with github actions

Error Description
While running command git push, I am getting following error: COPY failed: no source files were specified
Dockerfile
Dockerfile is like it:
# 拉取node:14作为构建工具
FROM node:14 AS build
# 工作目录为 app
WORKDIR /app
# 将以package结尾的json文件拷贝
COPY package*.json ./
RUN npm install -g pnpm
# 执行 安装依赖
RUN pnpm install
# 将 ts配置文件拷贝过去
COPY tsconfig.json ./
# 将public目录拷贝过去
COPY public public/
# 将src目录拷贝过去
COPY src src/
# 执行构建脚本
RUN pnpm run build
# 拉取nginx
FROM nginx:alpine
# 将构建好的文件夹拷贝到nginx中
COPY --from=build /app/build/ /usr/share/nginx/html
# 暴露端口9567
EXPOSE 9567
# 运行nginx
CMD ["nginx", "-g", "daemon off;"]
Github Actions Yaml
dev.yml(github actions)is like as shown below::
# This is a basic workflow to help you get started with Actions
name: Deploy Web De
# Controls when the workflow will run
on:
# Triggers the workflow on push or pull request events but only for the main branch
push:
branches: [main]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "deploy-web-dev"
deploy-web-dev:
environment:
development
# The type of runner that the job will run on
runs-on:
ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- name: Checkout
uses: actions/checkout#v3
- name: Install pnpm
uses: pnpm/action-setup#v2
with:
version: 6
- name: Install dependencies
run: pnpm install
- name: Build web dev
run: pnpm run build
- name: Log in to Docker Hub
uses: docker/login-action#v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Reset dockerignore
run: |
echo "*" > .dockerignore
echo "!dist" >> .dockerignore
- name: Build and push images
env:
COMMIT_SHA_TAG: development-${{ github.sha }}
LATEST_DEV_TAG: dev-latest
PRIVATE_DOCKERHUB_REGISTRY: ${{ secrets.PRIVATE_DOCKERHUB_REGISTRY }}
PRIVATE_DOCKERHUB_USERNAME: ${{ secrets.PRIVATE_DOCKERHUB_USERNAME }}
PRIVATE_DOCKERHUB_PASSWORD: ${{ secrets.PRIVATE_DOCKERHUB_PASSWORD }}
run: |
docker build . -t cloud-music:$COMMIT_SHA_TAG -t cloud-music:$LATEST_DEV_TAG -t $PRIVATE_DOCKERHUB_REGISTRY/cloud-music:$COMMIT_SHA_TAG -t $PRIVATE_DOCKERHUB_REGISTRY/cloud-music:$LATEST_DEV_TAG
docker push cloud-music:$COMMIT_SHA_TAG
docker push cloud-music:$LATEST_DEV_TAG
docker login -u $PRIVATE_DOCKERHUB_USERNAME -p $PRIVATE_DOCKERHUB_PASSWORD $PRIVATE_DOCKERHUB_REGISTRY
docker push $PRIVATE_DOCKERHUB_REGISTRY/cloud-music:$COMMIT_SHA_TAG
docker push $PRIVATE_DOCKERHUB_REGISTRY/cloud-music:$LATEST_DEV_TAG
Jobs Log
Jobs log:
Error Position
Error in line 23
1
Run docker build . -t cloud-music:$COMMIT_SHA_TAG -t cloud-music:$LATEST_DEV_TAG -t $PRIVATE_DOCKERHUB_REGISTRY/cloud-music:$COMMIT_SHA_TAG -t $PRIVATE_DOCKERHUB_REGISTRY/cloud-music:$LATEST_DEV_TAG
2
docker build . -t cloud-music:$COMMIT_SHA_TAG -t cloud-music:$LATEST_DEV_TAG -t $PRIVATE_DOCKERHUB_REGISTRY/cloud-music:$COMMIT_SHA_TAG -t $PRIVATE_DOCKERHUB_REGISTRY/cloud-music:$LATEST_DEV_TAG
3
docker push cloud-music:$COMMIT_SHA_TAG
4
docker push cloud-music:$LATEST_DEV_TAG
5
6
docker login -u $PRIVATE_DOCKERHUB_USERNAME -p $PRIVATE_DOCKERHUB_PASSWORD $PRIVATE_DOCKERHUB_REGISTRY
7
docker push $PRIVATE_DOCKERHUB_REGISTRY/cloud-music:$COMMIT_SHA_TAG
8
docker push $PRIVATE_DOCKERHUB_REGISTRY/cloud-music:$LATEST_DEV_TAG
9
shell: /usr/bin/bash -e {0}
10
env:
11
PNPM_HOME: /home/runner/setup-pnpm/node_modules/.bin
12
COMMIT_SHA_TAG: development-6ba24b062419ef744d2642e2f9eee97dabb9a63e
13
LATEST_DEV_TAG: dev-latest
14
PRIVATE_DOCKERHUB_REGISTRY: ***
15
PRIVATE_DOCKERHUB_USERNAME: ***
16
PRIVATE_DOCKERHUB_PASSWORD: ***
17
Sending build context to Docker daemon 3.584kB
18
19
Step 1/12 : FROM node:14 AS build
20
---> 903c2c873ea4
21
Step 2/12 : WORKDIR /app
22
---> Running in f80bdf0901cf
23
COPY failed: no source files were specified
24
Removing intermediate container f80bdf0901cf
25
---> 3221d5124e85
26
Step 3/12 : COPY package*.json ./
27
Error: Process completed with exit code 1.
Project Structure
Here is my project structure.
enter image description here
Please help me in solving this error.
Thanks in advance!!
I hope you might solved this issue. ANyhow my reply is to help others for reference. I too faced the same problem and solved by the following changes made in workflow.yml. You need to mention the docker packages and docker file directory in workflow by cd
workflow at the time of error
run: docker build . --file Dockerfile --tag nodejs:$(date +%s)
Fix:
run: |
cd app
docker build . --file Dockerfile --tag nodejs:$(date +%s)

How can I copy `.git` directory to the container with GitHub actions?

I have a GitHub actions CI which builds a my app in the last version of this app .git directory is mandatory for building it the problem is that GitHub action don't remove it in the docker build step of the CI.
Here is my CI template:
on:
push:
pull_request:
jobs:
build:
runs-on: ubuntu-20.04
if: github.ref == 'refs/heads/3.3.5-MV'
steps:
- uses: actions/checkout#v2
-
name: Set up QEMU
uses: docker/setup-qemu-action#v1
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action#v1
-
name: Login to DockerHub
uses: docker/login-action#v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and push
id: docker_build
uses: docker/build-push-action#v2
with:
file: ./Dockerfile
tags: foo/bar:latest
push: true
-
name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}
The Dockerfile
FROM ubuntu:focal
ENV TZ=Europe/Paris
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN apt update && apt upgrade -y && apt install -y [all my dependencies]
WORKDIR /usr/src/app
COPY . .
WORKDIR /usr/src/app/build
#default path on docker image /usr/local
RUN cmake ../ -DCMAKE_INSTALL_PREFIX=/usr/local/ -DTOOLS=0
RUN make -j $(nproc) install
WORKDIR /usr/local/bin
The issue is in the docker/build-push-action#v2 action, which by default ignores the checkout created using the actions/checkout#v2 action:
By default, this action uses the Git context so you don't need to use the actions/checkout action to check out the repository because this will be done directly by BuildKit.
The git reference will be based on the event that triggered your workflow and will result in the following context: https://github.com/<owner>/<repo>.git#<ref>.
When you pass a git build context to docker build, it won't
include the .git directory.
If you read through the documentation for the docker/build-push-action#v2 action, you'll see that you can override this behavior:
However, you can use the Path context using the context input alongside the actions/checkout action to remove this restriction.
You would need to modify your workflow so that it includes an explicit
context: ., like this:
name: Build and push
id: docker_build
uses: docker/build-push-action#v2
with:
context: .
file: ./Dockerfile
tags: foo/bar:latest
push: true
I've put together an example repository that demonstrates this here; you can see the verification in this build run.

Docker compose fails with 'COPY failed: stat usr/src/app/dist: file does not exist' - only on github actions

I'm creating web application (angular + nest.js) and I'm trying to make multi stage build - I want to reduce size of docker image.
Angular build works good.
Nest.js one builds successfully on my pc using docker compose build, but fails on github actions with following error: Status: COPY failed: stat usr/src/app/dist: file does not exist, Code: 1
What can i do to fix it?
Dockerfile:
FROM node:16.13.1-alpine AS build
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install --only=development
RUN npm run build
COPY . .
FROM node:16.13.1-alpine
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install --only=production
COPY . .
COPY --from=build /usr/src/app/dist ./dist
EXPOSE 7000
CMD ["node", "dist/main"]
previous single stage Dockerfile (builds successfully):
FROM node:16.13.1-alpine
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
RUN npm run build
COPY . .
EXPOSE 7000
CMD [ "npm", "start" ]
docker-compose.yml:
version: '3.8'
services:
backend:
container_name: nestjs
image: ghcr.io/<gh-nickname/repo-name>/backend
build:
context: backend
dockerfile: Dockerfile
ports:
- 7000:7000
frontend:
container_name: angular
image: ghcr.io/<gh-nickname/repo-name>/frontend
build:
context: frontend
dockerfile: Dockerfile
ports:
- 8000:80
github workflow file:
name: Build and publish to github packages
on:
push:
branches:
- master
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push-image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout
uses: actions/checkout#v2
- name: Log in to the Container registry
uses: docker/login-action#v1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action#v3
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Build image
run: docker compose build
- name: Publish image
run: docker compose push
Try with the following Dockerfile:
FROM node:16.13.1-alpine AS build
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install --only=development
RUN npm run build
COPY . .
FROM node:16.13.1-alpine
COPY --from=build /usr/src/app/dist ./dist
EXPOSE 7000
CMD ["node", "dist/main"]
Caching multistage builds on CI Servers is not that easy as locally. You have to tell it where to get the layers from. As schema:
docker build --target build-image --cache-from=you/repo/backend:build-stage --tag you/repo/backend:build-stage
docker build --target prod-image --cache-from=you/repo/backend:build-stage --cache-from=you/repo/backend:prod-stage --tag you/repo/backend:prod-stage
docker push
So for GH Actions you can use the internal caching of GH and do something like:
steps:
- name: Build base image
id: docker_build_base
uses: docker/build-push-action#v2
with:
context: .
file: Dockerfile
push: false
cache-from: |
type=gha,scope=base
cache-to: |
type=gha,scope=base,mode=max
target: base
tags: you/repo/backend:build-stage
- name: Build prod image
id: docker_build_prod
uses: docker/build-push-action#v2
with:
context: .
file: Dockerfile
push: true
cache-from: |
type=gha,scope=prod
type=gha,scope=base
cache-to: |
type=gha,scope=prod,mode=max
target: prod
tags: you/repo/backend:prod-stage
Remark: It's showing you the right direction and no copy&paste solution. Please adjust as you need..
I managed to solved it by moving COPY . . line before RUN npm run build

Resources