@@ -362,25 +362,42 @@ docker compose logs
362362
363363Docker 이미지를 빌드하기 위해선 먼저 ` Dockerfile ` 을 작성해야 합니다. 저는 제가 현재 진행하고 있는 Next.js 애플리케이션을 기준으로 Docker 이미지를 생성하겠습니다.
364364
365+ ### Next.js standalone
366+
367+ ` Next.js ` 애플리케이션에서 어떠한 설정을 하지 않고 Docker 이미지를 빌드하는 경우 다음과 같이 Docker 이미지 용량이 매우 커집니다.
368+
369+ <img src =" /assets/img/raspberry-pi/docker/pic12.avif " alt =" pic12 " style =" box-shadow : 0 4px 8px 0 rgba (0 , 0 , 0 , 0.2 ), 0 6px 20px 0 rgba (0 , 0 , 0 , 0.19 ); border-radius : 0.5rem " />
370+
371+ ` Next.js ` 에서는 프로덕션 배포에 필요한 파일만 포함해 Docker를 활용한 배포에 유용한 빌드 방식인 ` standalone ` 을 지원합니다. 다음 사진과 같이 ` next.config.mjs ` 파일에서 ` output: "standalone" ` 을 설정합니다.
372+
373+ <img src =" /assets/img/raspberry-pi/docker/pic11.avif " alt =" pic11 " style =" box-shadow : 0 4px 8px 0 rgba (0 , 0 , 0 , 0.2 ), 0 6px 20px 0 rgba (0 , 0 , 0 , 0.19 ); border-radius : 0.5rem " />
374+
365375### .dockerignore 생성하기
366376
367377` .dockerignore ` 파일은 Docker가 이미지를 빌드할 때 복사하지 말아야 할 파일이나 디렉토리를 지정하는 파일입니다. 이 파일은 Docker Context 내에 불필요한 파일들이 빌드 이미지에 포함되는 것을 방지하여, 빌드 속도를 높이고 이미지 크기를 줄이는 데 중요한 역할을 합니다.
368378
369379` Dockerfile ` 을 작성하기 전에 프로젝트 최상단 디렉토리에서 ` .dockerignore ` 파일을 생성하고 다음과 같이 작성합니다.
370380
371381``` bash
372- # Node.js 환경
382+ # 의존성 파일
373383node_modules
374384
375385# Git 관련 파일
376386.git
377387.gitignore
378-
379- # 환경 설정 파일
380- .env
388+ .github
381389
382390# Next.js 빌드 결과물
383391.next
392+
393+ # 기타
394+ .eslintrc.json
395+ .prettierrc.json
396+ LICENSE
397+ README.md
398+ build.sh
399+ Dockerfile
400+ .dockerignore
384401```
385402
386403위의 내용을 설명하자면 다음과 같습니다.
@@ -389,18 +406,18 @@ node_modules
389406
390407 Node.js의 의존성 파일이 저장된 디렉토리로, 보통 컨테이너 안에서 생성하므로 복사할 필요가 없습니다.
391408
392- - ` .git ` 과 ` .gitignore `
409+ - ` .github ` , ` . git` , ` .gitignore `
393410
394411 Git 관련 파일을 컨테이너 안에 포함할 필요가 없습니다.
395412
396- - ` .env `
397-
398- 환경 변수 정보는 보통 보안 상의 이유로 컨테이너 이미지에 포함하지 않는 것이 좋습니다.
399-
400413- ` 빌드 결과물 `
401414
402415 빌드 후 생성되는 파일이 저장된 디렉토리로, 보통 컨테이너 안에서 빌드 과정이 필요한 경우 컨테이너 안에서 생성하므로 복사할 필요가 없습니다.
403416
417+ - ` 기타 `
418+
419+ 애플리케이션 실행에 필요하지 않은 파일을 제외합니다.
420+
404421` .dockerignore ` 파일을 사용했을 때의 장점은 다음과 같습니다.
405422
406423- ` 속도 향상 `
@@ -424,6 +441,12 @@ Docker 이미지를 생성하기 위해선 먼저 `Dockerfile`을 작성해야
424441이후 프로젝트 최상단 디렉토리에서 ` Dockerfile ` 파일을 생성합니다. 다음은 Next.js 애플리케이션을 빌드하고 실행하는 Dockerfile 예시입니다.
425442
426443``` docker
444+ ###############################################################################################################
445+ # #
446+ # Notice: 해당 Dockerfile을 사용하기 위해선 먼저 next.config.mjs 파일에서 output이 "standalone"으로 설정되어야 합니다. #
447+ # #
448+ ###############################################################################################################
449+
427450# 1. 빌드 단계
428451# 생성할 Docker 이미지의 베이스가 되는 이미지를 지정합니다.
429452FROM node:20-alpine AS build
@@ -438,26 +461,22 @@ COPY package.json package-lock.json ./
438461
439462# 1-3. 의존성 설치
440463# 컨테이너 안에서 명령어를 실행하고 이미지를 빌드합니다.
441- RUN npm install --force
464+ RUN npm install
442465
443466# 1-4. 애플리케이션 코드 복사
444467# 현재 디렉토리의 모든 파일을 /app 디렉토리로 복사합니다.
445468COPY . .
446469
447- # 1-5. 환경 변수 설정
448- ENV NEXT_PUBLIC_BACKEND_URL=https://mafiacamp.p-e.kr
449-
450- # 1-6. 애플리케이션 빌드
470+ # 1-5. 애플리케이션 빌드
451471RUN npm run build
452472
453473# 2. 런타임 단계
454474FROM node:20-alpine
455475
456476# 2-1. 빌드 결과물과 필요한 파일만 복사
457477WORKDIR /app
458- COPY --from=build /app/.next ./.next
459- COPY --from=build /app/node_modules ./node_modules
460- COPY --from=build /app/package.json ./package.json
478+ COPY --from=build /app/.next/standalone ./
479+ COPY --from=build /app/.next/static ./.next/static
461480COPY --from=build /app/public ./public
462481
463482# 2-2. 포트 설정
@@ -467,13 +486,13 @@ EXPOSE 3000
467486# 2-3. 애플리케이션 실행
468487# 컨테이너가 시작될 때 실행할 기본 명령어를 지정합니다.
469488# CMD는 Dockerfile에서 한 번만 사용할 수 있습니다.
470- CMD [ "npm ", "run", "start " ]
489+ CMD [ "node ", "server.js " ]
471490```
472491
473492` Dockerfile ` 을 작성한 후 다음 명령어를 입력하여 Docker 이미지를 빌드합니다.
474493
475494``` bash
476- docker build -t mafiacamp-fe .
495+ docker build -t solitour-frontend:v1.1.0 .
477496```
478497
479498각 단계를 자세히 설명하자면 다음과 같습니다.
@@ -523,13 +542,11 @@ COPY package.json package-lock.json ./
523542``` docker
524543# 1-3. 의존성 설치
525544# 컨테이너 안에서 명령어를 실행하고 이미지를 빌드합니다.
526- RUN npm install --force
545+ RUN npm install
527546```
528547
529548` RUN ` 은 컨테이너 안에서 명령어를 실행할 때 사용하는 명령어입니다. 위의 예시에서는 ` npm install ` 명령어로 ` package.json ` 에 지정된 의존성을 설치합니다.
530549
531- 참고로 ` --force ` 옵션을 사용한 이유는 ` Next.js v15.0.2 ` 를 기준으로 ` React 19 RC ` 를 사용하고 있기 때문에 라이브러리 설치가 안되는 문제를 방지하기 위해 추가하였습니다. 불필요한 경우 ` --force ` 옵션을 제외하면 됩니다.
532-
533550<br />
534551
535552** 1-4. 애플리케이션 코드 복사**
@@ -544,21 +561,10 @@ COPY . .
544561
545562<br />
546563
547- ** 1-5. 환경 변수 설정**
548-
549- ``` docker
550- # 1-5. 환경 변수 설정
551- ENV NEXT_PUBLIC_BACKEND_URL=https://mafiacamp.p-e.kr
552- ```
553-
554- ` ENV ` 는 환경 변수를 설정하는 명령어입니다. [ 위에서 생성한 .dockerignore 파일] ( #dockerignore-생성하기 ) 에는 ` .env ` 파일을 제외하도록 설정하였기 때문에 애플리케이션 빌드 전에 필요한 환경 변수를 설정해야 합니다.
555-
556- <br />
557-
558- ** 1-6. 애플리케이션 빌드**
564+ ** 1-5. 애플리케이션 빌드**
559565
560566``` docker
561- # 1-6 . 애플리케이션 빌드
567+ # 1-5 . 애플리케이션 빌드
562568RUN npm run build
563569```
564570
@@ -582,9 +588,8 @@ FROM node:20-alpine
582588``` docker
583589# 2-1. 빌드 결과물과 필요한 파일만 복사
584590WORKDIR /app
585- COPY --from=build /app/.next ./.next
586- COPY --from=build /app/node_modules ./node_modules
587- COPY --from=build /app/package.json ./package.json
591+ COPY --from=build /app/.next/standalone ./
592+ COPY --from=build /app/.next/static ./.next/static
588593COPY --from=build /app/public ./public
589594```
590595
@@ -610,10 +615,10 @@ EXPOSE 3000
610615# 2-3. 애플리케이션 실행
611616# 컨테이너가 시작될 때 실행할 기본 명령어를 지정합니다.
612617# CMD는 Dockerfile에서 한 번만 사용할 수 있습니다.
613- CMD [ "npm ", "run", "start " ]
618+ CMD [ "node ", "server.js " ]
614619```
615620
616- ` CMD ` 는 컨테이너가 시작될 때 실행할 명령어를 지정하는 명령어입니다. ` CMD ` 는 하나의 Dockerfile 안에서 한 번만 사용할 수 있습니다. 위의 예시에서는 ` npm run start ` 명령어를 실행하여 Next.js 애플리케이션을 실행합니다.
621+ ` CMD ` 는 컨테이너가 시작될 때 실행할 명령어를 지정하는 명령어입니다. ` CMD ` 는 하나의 Dockerfile 안에서 한 번만 사용할 수 있습니다. 위의 예시에서는 ` node server.js ` 명령어를 실행하여 Next.js 애플리케이션을 실행합니다.
617622
618623<br />
619624
@@ -622,53 +627,54 @@ CMD [ "npm", "run", "start" ]
622627Dockerfile이 있는 디렉토리에서 터미널을 열고 다음 명령어를 입력하여 Docker 이미지를 빌드합니다.
623628
624629``` bash
625- docker build -t mafiacamp-fe .
630+ docker build -t solitour-frontend:v1.1.0 .
626631```
627632
628633아래 결과는 위의 ` Dockerfile ` 을 기반으로 Docker 이미지를 빌드한 결과 예시입니다.
629634
630635``` bash
631- PS C:\U sers\u ser\문 서\v scode\w eb12-MafiaCamp\F E> docker build -t mafiacamp-fe .
632- [+] Building 140.9s (15/15) FINISHED docker:desktop-linux
633- => [internal] load build definition from Dockerfile 0.0s
634- => => transferring dockerfile: 1.93kB 0.0s
635- => [internal] load metadata for docker.io/library/node:20-alpine 1.8s
636- => [internal] load .dockerignore 0.0s
637- => => transferring context: 174B 0.0s
638- => [build 1/6] FROM docker.io/library/node:20-alpine@sha256:c13b26e7e602ef2f1074aef304ce6e9b7dd284c419b35d89fcf3cc8e44a8def9 0.0s
639- => => resolve docker.io/library/node:20-alpine@sha256:c13b26e7e602ef2f1074aef304ce6e9b7dd284c419b35d89fcf3cc8e44a8def9 0.0s
640- => [internal] load build context 0.0s
641- => => transferring context: 6.29kB 0.0s
642- => CACHED [build 2/6] WORKDIR /app 0.0s
643- => CACHED [build 3/6] COPY package.json package-lock.json ./ 0.0s
644- => CACHED [build 4/6] RUN npm install --force 0.0s
645- => [build 5/6] COPY . . 0.2s
646- => [build 6/6] RUN npm run build 77.1s
647- => [stage-1 3/6] COPY --from=build /app/.next ./.next 1.2s
648- => [stage-1 4/6] COPY --from=build /app/node_modules ./node_modules 4.5s
649- => [stage-1 5/6] COPY --from=build /app/package.json ./package.json 0.2s
650- => [stage-1 6/6] COPY --from=build /app/public ./public 0.1s
651- => exporting to image 45.0s
652- => => exporting layers 33.8s
653- => => exporting manifest sha256:1cbf4b5bee24744bfe02047906dab35edfd26e2d7e859d2d48126d5976948c26 0.0s
654- => => exporting config sha256:d667149ae2af3795ca5b414568d640435664cb894727eb73af12f28b220ae24e 0.0s
655- => => exporting attestation manifest sha256:a445a77eb5e50e332d06b5145d3437746bcb35a2f7f3596b9b277c089bab4dad 0.0s
656- => => exporting manifest list sha256:d3e238644af5f4a6d2a27b9fc4051e83d1fb8f133120608debaebc30f9f8c0a2 0.0s
657- => => naming to docker.io/library/mafiacamp-fe:latest 0.0s
658- => => unpacking to docker.io/library/mafiacamp-fe:latest 11.0s
636+ PS C:\U sers\u ser\v scode\s olitour-frontend> docker build -t solitour-frontend:v1.1.0 .
637+ [+] Building 130.2s (14/14) FINISHED docker:desktop-linux
638+ => [internal] load build definition from Dockerfile 0.1s
639+ => => transferring dockerfile: 2.07kB 0.0s
640+ => [internal] load metadata for docker.io/library/node:20-alpine 2.0s
641+ => [internal] load .dockerignore 0.0s
642+ => => transferring context: 256B 0.0s
643+ => [internal] load build context 0.2s
644+ => => transferring context: 37.71kB 0.2s
645+ => [build 1/6] FROM docker.io/library/node:20-alpine@sha256:053c1d99e608fe9fa0db6821edd84276277c0a663cd181f4a3e59ee20f5f07ea 0.0s
646+ => => resolve docker.io/library/node:20-alpine@sha256:053c1d99e608fe9fa0db6821edd84276277c0a663cd181f4a3e59ee20f5f07ea 0.0s
647+ => CACHED [build 2/6] WORKDIR /app 0.0s
648+ => CACHED [build 3/6] COPY package.json package-lock.json ./ 0.0s
649+ => CACHED [build 4/6] RUN npm install 0.0s
650+ => [build 5/6] COPY . . 1.5s
651+ => [build 6/6] RUN npm run build 114.9s
652+ => [stage-1 3/5] COPY --from=build /app/.next/standalone ./ 0.8s
653+ => [stage-1 4/5] COPY --from=build /app/.next/static ./.next/static 0.2s
654+ => [stage-1 5/5] COPY --from=build /app/public ./public 0.2s
655+ => exporting to image 5.4s
656+ => => exporting layers 3.5s
657+ => => exporting manifest sha256:343b66796797d47af85f9439352ac3970a45f0ab0c09061ee1884c6b0be46ed0 0.0s
658+ => => exporting config sha256:0fba297b2ce1a37d4b3752a1f0d08eec1421da635cc1a4e73c486ca2a763eef6 0.0s
659+ => => exporting attestation manifest sha256:2b1c02b349dc52fecd6a415c50aa0fb34d9fa3dc61291cc46631e479fe7cf225 0.0s
660+ => => exporting manifest list sha256:fdb0336a57551b95032c4dc8cc4485e33d0369b4fa8c7ec9b6d5ca81b5f323f3 0.0s
661+ => => naming to docker.io/library/solitour-frontend:v1.1.0 0.0s
662+ => => unpacking to docker.io/library/solitour-frontend:v1.1.0 1.7s
659663```
660664
665+ <img src =" /assets/img/raspberry-pi/docker/pic7.avif " alt =" pic7 " style =" box-shadow : 0 4px 8px 0 rgba (0 , 0 , 0 , 0.2 ), 0 6px 20px 0 rgba (0 , 0 , 0 , 0.19 ); border-radius : 0.5rem " />
666+
661667## Step 6 - 컨테이너 실행하기
662668
663669Docker 이미지가 빌드된 후 다음 명령어를 입력하여 컨테이너를 실행합니다.
664670
665671``` bash
666- docker run -p 3000:3000 --rm mafiacamp-fe
672+ docker run -p 3000:3000 --rm solitour-frontend:v1.1.0
667673```
668674
669675컨테이너를 실행한 결과는 다음과 같습니다.
670676
671- <img src =" /assets/img/raspberry-pi/docker/pic7 .avif " alt =" pic7 " style =" box-shadow : 0 4px 8px 0 rgba (0 , 0 , 0 , 0.2 ), 0 6px 20px 0 rgba (0 , 0 , 0 , 0.19 ); border-radius : 0.5rem " />
677+ <img src =" /assets/img/raspberry-pi/docker/pic10 .avif " alt =" pic10 " style =" box-shadow : 0 4px 8px 0 rgba (0 , 0 , 0 , 0.2 ), 0 6px 20px 0 rgba (0 , 0 , 0 , 0.19 ); border-radius : 0.5rem " />
672678
673679## 참고 자료
674680
0 commit comments