
분명 로컬에서 도커를 빌드하고 다시 빌드를 하게 되면 처음 빌드를 했을 때보다 빌드하는 시간이 빠르다... 근데 GitHub Actions을 이용하면서 도커를 빌드하고 몇 번을 빌드해도 도커 캐시가 동작하지 않는다는 걸 알았다... 이번 포스팅에서는 GitHub Actions으로 간단한 express앱을 빌드하고 docker hub push 해보겠다
Express 앱
먼저 아무 폴더에서
$ npm init
$ npm install express
{
"name": "docker-ci-prac",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node app.js"
},
"dependencies": {
"express": "^4.16.1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
이제 app.js 파일에 express로 간단한 어플리케이션을 만들어보겠다
const express = require('express');
const app = express();
const port = 8080;
app.use(cors());
app.use(express.json({ strict: false }));
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(port, () => {
console.log(`${port}포트를 리스닝중입니다`);
});
Dockerfile 작성
FROM node:16
WORKDIR /app
# package.json, package-lock.json 파일을 복사한다
COPY package*.json ./
# 필요한 패키지들을 설치
RUN npm install
# 로컬에서 작업했던 파일들을 복사한다
COPY . .
# 이미지를 실행할때 사용할 포트
EXPOSE 8080
CMD ["node", "app.js"]
도커 빌드하기전에 .dockerignore 파일을 만들어서 빌드 시에 필요 없는 파일을 제외해 주자
node_modules
npm-debug.log
빌드를 해보자

첫 빌드는 91초가 걸렸다 다시 한번 빌드해 보겠다

2.6초가 걸렸다. 첫 번째 빌드에 비해 시간이 확연히 줄어들었다 단계를 잘 살펴보면 CACHED라고 되어있고, 특별한 작업을 진행하지 않고 넘어가는 것을 볼 수 있다.
GitHub Actions를 이용한 빌드
현재 작업하는 폴더의 경로에서. github/workflows/docker-ci.yaml을 만들어주자 yaml을 파일의 이름은 무엇이든 상관없다
직접 만들어도 되고 아래의 그림처럼 Actions를 클릭해서 Docker image를 클릭해도 된다

name: Docker Image CI
on:
push:
branches: ['main'] # main브렌치에서 push를 하게되면 실행하게하는 트리거
jobs:
build:
runs-on: ubuntu-latest # 도커를 빌드를 하게될 os
steps:
- name: Check out the repo
uses: actions/checkout@v3
- name: Log in to Docker Hub
uses: docker/login-action@v2 # 도커 hub에 push하기위해 도커 아이디와 비번
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push # 빌드한 이미지를 나의 레지스트리로 push
id: docker_build
uses: docker/build-push-action@v2
with:
push: true
tags: alsgur721/docker-nose-prac:latest
한번 push를 하기 전에 DOCKER_USERNAME과 DOCKER_PASSWORD를 불러와야 하는데 앞에 secret가 붙어있는 걸 확인할 수 있다 secret는 액션을 할 때 필요한 환경변수나 암호를 저장하는 곳이다

나는 DOCKER_USERNAME, DOCKER_PASSWORD로 했기 때문에 각자 그에 맞는 도커의 아이디와 비밀번호를 기입하면 되겠다

secret을 작성했다면 위의 그림처럼 보이게 된다 이제 Push를 해보고 입력한 Docker Hub의 레지스트리를 확인해 보면 빌드한 이미지가 정상적을 Push 된 걸 확인할 수 있다

도커 캐시

특별히 크게 수정한 거 없이 2번 더 push를 했는데 시간이 줄어들지 않고 오히려 늘어나거나 비슷하다 분명 로컬에서 빌드를 하면 큰 수정 사항이 없다면 도커 캐시로 인해 처음 빌드를 했을 때보다 그다음 빌드 할 때 시간이 줄어들었던걸 확인했었다 근데 막상 GitHub Actions으로 push를 해보니 전혀 도커 캐시가 작동 중이지 않는다... GitHub Actions 로그를 확인해봐도 캐시가 작동 중인걸 확인할 수 없다..
일단 그 이유는 GitHub Actions의 러너는 매번 새로운 가상 환경에서 실행된다. 그래서 모든 작업은 새롭게 시작된다. GitHub에서 일부 환경을 위한 캐싱을 제공하지만 Docker 레이어에 대한 내용은 없다.
docker/build-push-action을 이용해 보자.
도커에서 공식적으로 제공하는 docker/build-push-action을 이용해 도커 이미지의 build, push를 할 수 있다. 이때 buildx라는 CLI 플러그인을 사용하는데, 빌더 툴킷인 BuildKit의 다양한 기능을 모두 사용할 수 있게 해 준다. 또한 GitHub Actions에 직접 캐시를 저장시키는 GitHub Cache API를 제공하기 때문에 이를 활용해보려 한다.
name: Docker Image CI
on:
push:
branches: ['main']
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Check out the repo
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1 # buildx 설정
- name: Log in to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
id: docker_build
uses: docker/build-push-action@v2
with:
push: true
tags: alsgur721/docker-nose-prac:v0.1
cache-from: type=gha # 여기서 gha 는 Guthub Actions 용 캐시를 의미한다.
cache-to: type=gha,mode=max
우선 buildx 설정을 해주고, docker/build-push-action@v2를 이용해 build와 push를 해주고 있다. 그리고 cache-from과 cache-to에 type=gha라고 입력해 준다. 이 부분에서 캐싱이 적용된다.
주의 사항으로는 docker 공식 docs에서 type=gha를 이용하는 캐싱은 실험 단계라고 나와있다.
buildx 0.6.0과 Buildkit 0.9.0부터는 type=gha 캐시를 사용할 수 있다. 여기서 gha는 GitHubActions의 약자이다
이렇게 작성해 주고 어떻게 달라지나 비교해 보겠다. 배포를 하면

아직 캐시가 적용된 상태가 아니기 때문에 전에 했던 배포시간이 비슷하다 다시 한번 재배포해보겠다

빌드한 시간이 2배가 줄어들었다

GitHub Actions 로그를 확인해보면 수정하지 않은 작업들은 CACHED로 되어 있는 걸 확인할 수 있다
사실 node:16 버전에서 많은 시간을 소비한 건 알고 있다 그래서 node:16-alpine을 하면 절약할 수 있다 하지만 여기서는 캐싱이 가능하다는 걸 보여주기 위해 한 것이니까 참고하면 되겠다
기술 출처
https://docs.docker.com/build/ci/github-actions/examples/#github-cache
Example workflows
docs.docker.com
'DevOps > Docker' 카테고리의 다른 글
[Docker] docker-compose의 docker 네트워크 (0) | 2023.01.24 |
---|---|
[Docker] ubuntu에서 docker & docker-compose 설치 방법 (0) | 2022.12.30 |
[Docker] docker 이미지 생성하기 (0) | 2022.12.12 |
[Docker] docker 로그 확인하기 (0) | 2022.12.05 |
[Docker] docker 볼륨 컨트롤하기 (0) | 2022.12.05 |