[Docker] Dockerfile 스크립트로 이미지 생성하고 Docker hub에 등록하기

rekv·2025년 3월 18일

Docker

목록 보기
5/12

컨테이너 개발

베이스 이미지

컨테이너를 개발할 때 기본이 되는 이미지

도커 허브에는 다양한 베이스 이미지들이 등록되어 있다.

  • 리눅스 배포판 : ubuntu, centos, debian, fedora, amazonlinux 등
  • 프로그래밍 언어 : node, golang, php, pythom, openjdk 등
  • NoSQL DB : redis, mongo, memcached 등
  • SQL DB : postgres, mysql, mariadb 등
  • Web 서버 : nginx, httpd 등
  • 서블릿/JSP 서버 : tomcat, jetty 등
  • 콘텐츠 관리 시스템 : wordpress, ghost 등
  • 컨테이너 : docker, swarm 등
  • CD/CI : maven, jenkins 등
  • 로그와 메트릭 분석 : ElasticSearch, Logstach, Kibana 등

컨테이너 개발 순서

  1. 디렉토리를 준비, 이미지에 포함시킬 파일들을 모은다.
  2. Dockerfile 작성
  3. 컨테이너에서 실행할 애플리케이션 코드를 작성하고 유닛 테스트 실행
  4. 이미지 빌드
  5. 컨테이너를 실행하여 동작을 확인

도커 파일

컨테이너를 만드는 등 일련의 작업들을 미리 선언함으로써 매번 해당 작업을 하지않고도 컨테이너 생성시 자동으로 등록된 작업이 실행된 후 컨테이너를 생성할 수 있는 파일

메뉴얼 작업을 기록한 Dockerfile 생성 (파일의 이름이 Dockerfile)하여 명령어로 빌드하면 이를 통해 도커 이미지가 생성된다.

예시

FROM  alpine:latest				# 베이스 이미지
RUN   apk update && apk add figlet		# 컨테이너에서 실행할 명령어
ADD   ./message /message			# 컨테이너에 추가할 파일, 현재 디렉토리의 message 파일을 컨테이너의 / 디렉토리에 배치
CMD   cat /message | figlet			# 컨테이너가 실행 된 후 실행할 명령어

많이 쓰는 커맨드

명령어설명
COPY [원본][사본]컨테이너 내 파일을 컨테이너의 다른 곳에 복사
ENV [변수]=[값]환경 변수 설정
EXPOSE [포트]공개 포트 설정
WORKDIR [경로]컨테이너 내에서 작업 디렉토리 지정, cd 같은 것
MAINTAINER [이름]이미지에 대한 작성자 추가

여기서 잠깐, CMD와 ENTRYPOINT, ADD 와 COPY는 서로 비슷해 보이는데 차이가 뭘까? (클릭)

이미지 빌드

docker build --tag [docker ID][이미지이름]:[버전][도커파일 경로]
ex. docker buiild --tage rekv/fistdocerimage:1.0 .

[버전]과 [도커파일] 사이에 띄어쓰기가 잘 안보이므로 주의

실행 및 확인

docker images
docker run [이미지이름]:[버전]

실습

url:8080/abc/test01로 접속하면 test01이라는 글자가 나오는 백엔드 프로젝트를 생성 후 bootJar 파일 빌드

FROM    openjdk:17-ea-slim-buster
EXPOSE  8080
ADD     ./build/libs/demo-0.0.1-SNAPSHOT.jar    /app.jar
CMD     java -jar /app.jar

Dockerfile을 생성하여 위의 스크립트를 작성

docker build --tag [사용자이름]/[이미지 이름]:[버전][Dockerfile 위치]

터미널에서 build 명령어를 이용하여 이미지 빌드

이미지가 생성된 모습


이미지를 컨테이너에서 실행한 다음 /abc/test01로 접속해보면 정상적으로 동작하는 걸 볼 수 있다.

도커 허브

Docker Hub는 Docker에서 관리하는 호스팅된 Docker 레지스트리

도커 허브(클릭)에서는 소프트웨어 공급업체, 오픈 소스 프로젝트 및 커뮤니티에서 제공하는 이미지 외에도 직접 만든 이미지도 등록이 가능하다.

docker push [docker ID]/[이미지 이름]:[버전]

도커 허브에 생성한 이미지를 push하는 명령어 (이미지 build가 선행되어야 한다.)

docker hub에 올라온 모습

실습

백엔드 프로젝트와 프론트엔드 프로젝트를 각각 도커 이미지로 생성한 다음 허브에 업로드하여 도커 컴포즈로 3계층 아키텍처가 실행될 수 있게 설정하기

🌟프로젝트 구조

project-root/

├── backend/
│ ├── Dockerfile ✅ 백엔드용
│ └── (소스코드, JAR 등)

└── frontend/
│ ├── Dockerfile ✅ 프론트엔드용
│ ├── nginx/default.conf
│ └── (Vue/React 프로젝트, dist 폴더 등)

├── docker-compose.yml

참고로 프로젝트는 위의 그림과 같이 구성하는 게 터미널에서 명령어를 입력할 떄 편하다.

💻프론트엔드

FROM    nginx:latest
EXPOSE  80
ADD     ./frotend/dist /usr/share/nginx/html
ADD		./frotend/nginx/default.conf /etc/nginx/conf.d/default.conf

앞선 docker-compose 실습에서는 베이스 이미지를 이용해 container를 동작시켰으므로 설정 및 배포될 파일을 docker-compose.yaml에서 지정했으나, 이제는 내가 만든 이미지를 등록하여 컨테이너에 올릴 것이므로 필요한 설정을 추가한다.

🛠️백엔드

백엔드도 프론트엔드와 마찬가지로 배포할 빌드 파일을 이미지에 등록한다.

FROM    openjdk:17-ea-slim-buster
EXPOSE  8080
ADD     ./backend/build/libs/[빌드 파일].jar:/app.jar"
CMD		java -jar /app.jar
ENV		DB_URL=jdbc:mariadb://db:3306/test
ENV		DB_USER=test
ENV		DB_PASSWORD=qwer1234

🌟여기서 잠깐, 환경변수(ENV)의 DB_URL을 보면 ip 주소가 아닌 db라고 적혀있다. 이는 docker-compose.yaml에서 함께 작성되어 실행될 db라는 이름의 컨테이너로 알아서 연결이 된다.

📝docker-compose.yaml

도커 컴포즈 정리(클릭)를 참고하여 작성

version: "3"

services:
  frontend:
    image: [프론트엔드 이미지]:[버전]
    ports:
      - 80:80

  backend:
    image: [백엔드 이미지]:[버전]
    ports:
      - 8080:8080
    depends_on:
      - db

  db:
    image: mariadb:latest
    ports:
      - 3306:3306
    volumes:
      - ./db:/var/lib/mysql
    environment:
      - MARIADB_ROOT_PASSWORD=qwer1234
      - MARIADB_DATABASE=test
      - MARIADB_USER=test
      - MARIADB_PASSWORD=qwer1234

그런데 실습을 하는 도중 localhost의 3306포트는 이미 다른 DB 실습 프로그램이 실행되고 있어, 나는 3307 포트로 db를 실행시켰다. 그래서 당연히 백엔드 도커 이미지도 db:3307로 연결해야 한다고 생각하고 3307을 적었는데, 연결이 되지 않았다.
이는 같은 compose 네트워크를 통해 해당 컨테이너에 직접 접근하는 경우이므로, 로컬에서 실행시킨 포트가 아닌 컨테이너 포트를 지정해야하기 떄문이었다.

✅ 정리

접속 위치DB_URL 값포트
같은 Compose 네트워크의 백엔드 컨테이너jdbc:mariadb://db:3306/webContainer Port
외부 서버나 로컬 호스트에서 접속jdbc:mariadb://localhost:3307/webLocal Port
외부 네트워크 서버에서 접속jdbc:mariadb://<서버IP>:3307/webLocal Port

0개의 댓글