Docker 만 사용하는 경우 + Docker compose 까지 사용하는 경우를 모두 다뤘습니다.
필요하신 부분만 보셔도 괜찮습니다!! 둘 다 사용할 수 있어야 할 것 같아서 같이 진행했습니다.
❓자. Github 에 올리지 않고, Local → Github Actions → cloud Server 옮길 수 있는 방법은 뭘까?
❓ 그럴거면 Github actions 를 왜 써. 그냥 코드도 clone 으로 받지. 탈락!!!
FROM your_base_image
WORKDIR /usr/src/app
COPY .env ./
ENV DATABASE_URL=<your_database_url>
ENV JWT_SECRET=<your_jwt_secret>
❓ Dockerfile 도 Github 에 올려야 Github Actions 로 실행을 시키는 거잖아. env 에 있는 정보가 노출될까봐 안올렸는데, env 정보를 Dockerfile 에 옮기고, 이걸 올리면 env 를 올리는 것과 같은거잖아.
# SSH 내부에서 Github Actions Secrets 을 받아서, .env 파일에 변수를 직접 넣는다.
if [ ! -f .env ]; then
echo "DOCKER_IMAGE_TAG=${{ secrets.DOCKER_IMAGE_TAG }}" > .env
echo "DATABASE_URL=${{ secrets.DATABASE_URL }}" >> .env
echo "JWT_SECRET=${{ secrets.JWT_SECRET }}" >> .env
fi
# 아래처럼 Server 내 .env 경로를 찾아서 Docker 가 실행되는 폴더 내부에 마운트 해야합니다.
docker run -d -p 443:443 -v /root/app/.env:/usr/src/app/.env:ro -v /etc/letsencrypt:/etc/letsencrypt:ro
# 볼륨을 생성해서 마운트된 파일도 볼 수 있습니다~
docker run -it -v /host/path:/container/path <이미지 이름 또는 ID> /bin/bash
.env 파일을 올리는 법을 해결했더니, docker-compose.yml 은 어떻게 올려야하지?
💬 docker-compose.yml 에는 중요한 정보를 올리지 않는 게 좋습니다.
.env → Github Actions Secrets 사용
docker-compose.yml
docker-compose.yml 은 Github 에 올려도 된다는 점을 활용하자!!
❓ NCP Server 에서 원격서버로부터 가져오려고 할 때, Artifact 의 URL 로 가져오는데,
사실 이 과정은 잘 모르기도 하고, 어려워서 깊이는 안 찾아봤지만, 딱히 자료가 없어서…. Pass!!
# 만약 docker-compose.yml 이 없다면 다운을 받고 있다면 Pass!
if [ ! -f docker-compose.yml ]; then
curl -o docker-compose.yml https://raw.githubusercontent.com/zzub-zzub-bak-sa/backend/deploy/docker-compose.yml
fi
# docker compose 를 설치하는 코드, 이후에 docker-compose run 실행 가능!
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
# 로그인은 가능하지만, 이후 SSH 접속을 하면 다시 권한이 없어진다.
- name: Login to NCP Container Registry
uses: docker/login-action@v2
with:
registry: ${{ secrets.NCP_CONTAINER_REGISTRY }}
username: ${{ secrets.NCP_ACCESS_KEY }}
password: ${{ secrets.NCP_SECRET_KEY }}
# 기존 컨테이너, image 를 멈추거나 삭제 등 여러 과정이 필요합니다. 마지막 부분에 코드 드릴게요
echo ${{ secrets.NCP_SECRET_KEY }} | docker login -u ${{ secrets.NCP_ACCESS_KEY }} ${{ secrets.NCP_CONTAINER_REGISTRY }} --password-stdin
docker pull ${{ secrets.NCP_CONTAINER_REGISTRY }}/${{ secrets.NCP_CONTAINER_REPO }}:latest
// 이런 식으로 맨 위로 올려야함.
async function bootstrap() {
dotenv.config();
# 아래처럼 -p 옵션을 통해 Port 를 열어줘야한다.
docker run -d -p 443:443
“너가 이기나 내가 이기나 한번해보자” 는 심정으로 계속 수정 → 실행 → 수정 계속…하아..힘들었다
매일 속으로만 생각하고, 너무 바빠서 다음에 다음에 하면서 미뤘는데 오늘 끝장을 봤다.
너무 힘들었고, NCP registry 를 쓰면서 복잡해지기도 하고, Docker-compose 랑 Docker 만 쓰는
두가지를 모두 해결해서 그런지, 시간이 너무 오래 걸렸지만 매우 좋았다. 다 끝내니까 내가 이긴 기분이다!!!
# 기본 이미지 설정 (Node.js)
FROM node:20
# 앱 디렉토리 생성 및 설정
WORKDIR /usr/src/app
# 패키지 파일 복사 및 설치
COPY package*.json ./
RUN npm install
# 소스 코드 복사
COPY . .
# 앱 빌드
RUN npm install --production=false
RUN npx prisma generate --schema=src/db/prisma/schema.prisma
RUN npm run build \
rm -rf node_modules \
npm install --production=true
# 컨테이너 실행 시 실행될 명령어
CMD ["npm", "run", "start:prod"]
version: '3'
services:
app:
image: registry URL/Repo Name:Image Tag
container_name: 원하는 컨테이너 이름 지정
ports:
- "443:443"
env_file:
- .env
volumes:
- /root/app/.env:/usr/src/app/.env
- /etc/letsencrypt:/etc/letsencrypt:ro
name: Build and Push Docker Image
on:
push:
branches:
- deploy
jobs:
build_and_push:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v2
- name: Cache node modules
uses: actions/cache@v2
with:
path: node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Login to NCP Container Registry
uses: docker/login-action@v2
with:
registry: ${{ secrets.NCP_CONTAINER_REGISTRY }}
username: ${{ secrets.NCP_ACCESS_KEY }}
password: ${{ secrets.NCP_SECRET_KEY }}
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: 20
- name: Build and Push Docker Image
run: |
docker build -t ${{ secrets.NCP_CONTAINER_REGISTRY }}/${{ secrets.NCP_CONTAINER_REPO }}:${{ secrets.DOCKER_IMAGE_TAG }} .
docker push ${{ secrets.NCP_CONTAINER_REGISTRY }}/${{ secrets.NCP_CONTAINER_REPO }}:${{ secrets.DOCKER_IMAGE_TAG }}
pull_from_registry:
runs-on: ubuntu-latest
needs: build_and_push
steps:
- name: Checkout Repository
uses: actions/checkout@v2
- name: connect ssh
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.DEV_HOST }}
username: ${{ secrets.DEV_USERNAME }}
password: ${{ secrets.DEV_PASSWORD }}
port: ${{ secrets.DEV_PORT }}
script : |
rm -rf app
if [ ! -d "app" ]; then
mkdir app
fi
cd app || exit
if [ ! -f .env ]; then
echo "DOCKER_IMAGE_TAG=${{ secrets.DOCKER_IMAGE_TAG }}" > .env
echo "DATABASE_URL=${{ secrets.DATABASE_URL }}" >> .env
echo "JWT_SECRET=${{ secrets.JWT_SECRET }}" >> .env
fi
cd
echo ${{ secrets.NCP_SECRET_KEY }} | docker login -u ${{ secrets.NCP_ACCESS_KEY }} ${{ secrets.NCP_CONTAINER_REGISTRY }} --password-stdin
docker stop $(docker ps -q --filter ancestor=${{ secrets.NCP_CONTAINER_REGISTRY }}/${{ secrets.NCP_CONTAINER_REPO }})
docker rm $(docker ps -aq --filter ancestor=${{ secrets.NCP_CONTAINER_REGISTRY }}/${{ secrets.NCP_CONTAINER_REPO }})
docker rmi ${{ secrets.NCP_CONTAINER_REGISTRY }}/${{ secrets.NCP_CONTAINER_REPO }}:latest
docker pull ${{ secrets.NCP_CONTAINER_REGISTRY }}/${{ secrets.NCP_CONTAINER_REPO }}:latest
docker run -d -p 443:443 -v /root/app/.env:/usr/src/app/.env:ro -v /etc/letsencrypt:/etc/letsencrypt:ro ${{ secrets.NCP_CONTAINER_REGISTRY }}/${{ secrets.NCP_CONTAINER_REPO }}:latest
docker image prune -f
name: Build and Push Docker Image
on:
push:
branches:
- deploy
jobs:
build_and_push:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v2
- name: Login to NCP Container Registry
uses: docker/login-action@v2
with:
registry: ${{ secrets.NCP_CONTAINER_REGISTRY }}
username: ${{ secrets.NCP_ACCESS_KEY }}
password: ${{ secrets.NCP_SECRET_KEY }}
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: 20
- name: Build and Push Docker Image
run: |
docker build -t ${{ secrets.NCP_CONTAINER_REGISTRY }}/${{ secrets.NCP_CONTAINER_REPO }}:${{ secrets.DOCKER_IMAGE_TAG }} .
docker push ${{ secrets.NCP_CONTAINER_REGISTRY }}/${{ secrets.NCP_CONTAINER_REPO }}:${{ secrets.DOCKER_IMAGE_TAG }}
pull_from_registry:
runs-on: ubuntu-latest
needs: build_and_push
steps:
- name: Checkout Repository
uses: actions/checkout@v2
- name: connect ssh
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.DEV_HOST }}
username: ${{ secrets.DEV_USERNAME }}
password: ${{ secrets.DEV_PASSWORD }}
port: ${{ secrets.DEV_PORT }}
script : |
if [ ! -d "app" ]; then
mkdir app
fi
cd app || exit
if [ ! -f .env ]; then
echo "DOCKER_IMAGE_TAG=${{ secrets.DOCKER_IMAGE_TAG }}" > .env
echo "DATABASE_URL=${{ secrets.DATABASE_URL }}" >> .env
echo "JWT_SECRET=${{ secrets.JWT_SECRET }}" >> .env
fi
if [ ! -f docker-compose.yml ]; then
curl -o docker-compose.yml https://raw.githubusercontent.com//Github_Repository_Name/Branch_Name/docker-compose.yml
fi
echo ${{ secrets.NCP_SECRET_KEY }} | docker login -u ${{ secrets.NCP_ACCESS_KEY }} ${{ secrets.NCP_CONTAINER_REGISTRY }} --password-stdin
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
docker stop $(docker ps -q --filter ancestor=${{ secrets.NCP_CONTAINER_REGISTRY }}/${{ secrets.NCP_CONTAINER_REPO }})
docker rm $(docker ps -aq --filter ancestor=${{ secrets.NCP_CONTAINER_REGISTRY }}/${{ secrets.NCP_CONTAINER_REPO }})
docker rmi ${{ secrets.NCP_CONTAINER_REGISTRY }}/${{ secrets.NCP_CONTAINER_REPO }}:latest
docker pull ${{ secrets.NCP_CONTAINER_REGISTRY }}/${{ secrets.NCP_CONTAINER_REPO }}:latest
docker-compose up -d
docker image prune -f