원래는 도커를 제대로 공부해보고 그 다음에 사용해보려 했었다.
근데 노트북 데탑을 왔다갔다하면서 개발할때마다 자꾸 에러를 뿜는다....
홧김에 세팅해보았다.
일단 미리 말하자면 나는 도커이미지로 개발환경 세팅만 해놓고 이미지 내부에 구현코드는 존재하지 않게 만들었다.
준비된 개발환경은 다음과 같다.
node + vite + vue
이번에 할 것은
1. Dockerfile 작성
2. docker compose 파일 작성
3. 핫 리로딩 개선
이 정도를 해보려고 한다. 배포환경 세팅은 다음에 따로 글을 작성해야겠다.
1. Dockerfile 작성
프로젝트 경로 최상단에 Dockerfile을 작성해준다.
# 만들려고 하는 image의 베이스가 되는 image
FROM node:lts-alpine
# base directory 라고 보면 된다.
WORKDIR /app
# 이미지 생성 시 호스트의 파일을 이미지 내부로 복사한다.
COPY package.json .
COPY yarn.lock .
# 이미지를 빌드할 때 'yarn' 명령을 실행한다.
RUN yarn
# 외부에 공개할 포트
EXPOSE 3000
# yarn dev 명렁어 실행
CMD [ "yarn", "dev" ]
해당 도커 파일을 실행시켜서 이미지를 만들 수 있다.
아래처럼 작성하면 된다.
경로는 현재 터미널이 위치한 경로가 프로젝트 최상단이라면 그냥 점(.) 하나만 찍으면 된다.
나는 back단과 front단을 나눠서 개발중이라서 구분을 위해 frontApp 이라는 이름으로 이미지 태그명을 작성했다.
태그명이 있어야 사용하기 편하므로 왠만하면 작성해주자.
docker build <Dockerfile의 경로> -t <이미지 태그명>
이미지가 잘 생성이 되었는지 확인해보자
docker images
생성이 무사히 되었다면 이미지를 실행시켜보자.
Dockerfile에서 3000번 포트를 열어놓았으니 image의 3000번 포트를 로컬의 3001번 포트에 매핑시켜보겠다.
- -p: 포트번호 할당 옵션
docker run -p 3001:3000 frontApp
브라우저에서 localhost:3001 로 접속이 되면 성공이다.
2. docker-compose.yml 작성
명령어로 docker 이미지를 매번 생성 및 실행하는것은 귀찮다.
이미지가 여러개일 경우 더욱 귀찮다.
이럴 때 docker compose를 사용하면 편하다.
docker-compose.yml라는 이름으로 작성하자.
아래의 코드에서 volumes가 무엇인지 의아할텐데
간단히 설명하자면 컨테이너 내부의 경로와 로컬의 특정 경로를 연결시켜준다.
나의 경우에는
docker-compose.yml 파일의 경로 기준으로 ./front에 내 프로젝트가 있고
컨테이너 내부의 /app에 프로젝트가 있다.
# 버전은 임의로 지정해도 상관없다.
version: '1.0'
services:
front: # 서비스명. 글쓴이는 front로 설정했다
image: 'realworld-vue-front' # 생성할 image명
container_name: 'front' # 생성할 container명
build:
context: . # 빌드할 도커파일의 경로
dockerfile: Dockerfile2 # 만일 도커파일명을 Dockerfile2라고 작성했다면 이렇게 작성하면 된다.
ports:
- '3001:3000' # docker run 명령어에서 포트번호 지정해준것과 같다.
volumes:
- './front:/app'
- '/app/node_modules'
volumes에서 '/app/node_modules'를 왜 추가했는지 의아해하는 사람들이 많을 것이다.
이유는 이러하다.
우리가 도커를 사용하는 목적은 개발환경은 이미지에 저장되어있는 환경 그대로를 사용하면서 코드만 수정하는 것이다.
그런데 volume을 사용하면 호스트의 node_modules 또한 바인딩된다.
즉, Dockerfile에서 yarn.lock파일을 이용하여 의존성을 install해도 무용지물이 되는것이다.
이러한 문제를 '/app/node_modules'를 추가해줌으로써 해결할 수 있다.
어떻게 해결이 되는지는 다음과 같다.
1. 이미지가 생성되면서 내부적으로 install을 하게 되고, 이미지 내부의 디펜던시가 freezing 된다.
2. volumes: './front:/app' - 호스트의 node_modules가 바인딩되며 컨테이너에 있던 node_modules는 숨겨진다.
2번까지가 우리가 직면한 문제의 원인이다.
'/app/node_modules'를 volume에 추가함으로써 해결이 된다.
3. volumes: '/app/node_modules' - 컨테이너 내부에 숨겨져있던 node_modules를 다시 바인딩한다.
이렇게 하면 호스트의 node_modules는 볼륨으로 관리가 되지 않게 된다.
이제 도커 컴포즈를 실행시켜보자.
- -f : cli로 실행할 땐 -f 플래그를 붙여준다.
- --build : 생성되어있는 이미지를 삭제하지 않고 다른 이미지로 새로 빌드하고 싶으면 사용한다.
- -d : detacted mode... 즉 background 모드로 실행해준다.
- --build : 이미지가 존재하더라도 새로 빌드해준다.
docker compose -f docker-compose.dev.yml up -d --build
3. vite.config.ts
이제부터는 윈도우 사용자들이 vite를 사용할 때의 문제다.
vite는 윈도우의 Linux Subsystem... 즉, WSL2 내부에서 사용하면 파일 추적을 하지 못하므로 핫 리로딩이 동작하지 않는다. (윈도우 Docker Desktop은 WSL2를 기반으로 동작한다.)
만약 윈도우 사용자라면 vite.config.ts에 설정을 추가하자.
(자세한 설정이 궁금하다면 링크에서 문서를 확인하자!)
export default defineConfig({
server: {
watch: {
usePolling: true,
}
},
})
여기까지 설정을 완료했다면 이제 개발을 시작하면 된다.
추가로 토이프로젝트용으로 내가 세팅한 코드 또한 올려본다.
나는 node_modules만 가지고 있는 node 기반 이미지를 만들어서 사용하고 있다.
즉, 개발환경(node버전, node_modules)만 고정해놓고 실제 코드는 깃허브로 관리한다.
git 같은 형상관리를 이용하여 코드를 공유하되, 테스트는 dependency 및 런타임 환경이 고정되어 있는 container에서 하는것이다.
프로젝트 구조는 이렇게 되어있다. 실제 프로젝트 폴더는 front다.
root
ㄴ docker-compose.dev.yml
ㄴ front
ㄴ Dockerfile.dev
docker-compose.dev.yml
version: '1.0'
# docker compose -f docker-compose.dev.yml up -d
# docker compose -f docker-compose.dev.yml down -v
services:
front:
image: 'realworld-vue-front'
container_name: 'front'
restart: always
build:
context: ./front
dockerfile: Dockerfile.dev
ports:
- '3000:3000'
volumes:
- ./front:/app
- front_volume:/app/node_modules
volumes:
front_volume:
Dockerfile.dev
FROM node:lts-alpine
WORKDIR /app
COPY package.json .
COPY yarn.lock .
RUN yarn install && yarn cache clean
EXPOSE 3000
CMD ["yarn", "dev"]
reference
'프로그래밍 > 기타' 카테고리의 다른 글
사이드 프로젝트에 사용하기 좋은 서비스 (0) | 2023.12.18 |
---|---|
깃허브 블로그에 댓글 기능 추가하기 (feat. Utterances, Disqus) (+ react, vue) (2) | 2022.02.08 |
[Vue.js] click 이벤트 submit 새로고침 방지 (0) | 2022.01.27 |
Vue 2에서 vue-cli 대신 Vite 사용하기 (0) | 2022.01.16 |
[nods.js] Express로 서버 구축하기 (w/o Generator) - 1 (0) | 2021.10.08 |