로컬환경

(MacBook-M시리즈칩)

docker build -t gamzaa/product-service:1.0 .
docker push gamzaa/product-service:1.0

 

서버(Linux, amd64 아키텍처)에서 이미지 가져오려했는데 실패

docker pull gamzaa/product-service:1.0

# 1.0: Pulling from gamzaa/product-service
# no matching manifest for linux/amd64 in the manifest list entries

 

 

원인

CPU 아키텍처 불일치 문제

  • 로컬: Apple Silicon(M2) - ARM64
  • 서버: 일반적인 클라우드 서버 - AMD64(x84_64)

로컬에서 이미지를 빌드할 때 ARM64 아키텍처용으로 빌드함

AMD64 아키텍처 서버에서는 실행할 수 없음

 

해결 방법

Docker Buildx 사용

Docker Buildx
: 여러 플랫폼용 이미지를 동시에 빌드할 수 있는 Docker의 확장 기능, 한 번의 명령으로 여러 아키텍처를 지원하는 이미지 생성

 

docker buildx build --platform linux/amd64,linux/arm64 -t gamzaa/product-service:1.0 --push .
docker pull gamzaa/product-service:1.0 #성공

현재 방식

  • 로컬에서 애플리케이션 빌드하여 JAR 파일 생성
  • Dockerfile(JDK설치, JAR파일 복사 및 실행 명령) 작성
  • 서버에 JAR파일과 Dockerfile 업로드
  • 서버에서 Dockerfile로 도커 이미지 빌드
  • 빌드된 이미지로 도커 컨테이너 실행

 

Docker Hub에 이미지 올려서 배포

 

1. Docker Hub(hub.docker.com) 계정 생성

 

2. 로컬에서 Dockerfile로 도커이미지 빌드

# 사용자이름/이미지이름:태그
docker buildx build --platform linux/amd64,linux/arm64 -t gamzaa/product-service:1.0 --push .

 

3. 로컬에서 Docker CLI 로그인

docker login

 

4. 빌드된 도커이미지를 Docker Hub에 푸시

docker push gamzaa/product-service:1.0

 

 

5. 서버에서 도커이미지 pull

docker pull gamzaa/product-service:1.0
docker run -d --name product-service -p 11002:11002 --restart always gamzaa/product-service:1.0

 

'DevOps > Docker' 카테고리의 다른 글

Docker 배포 시 아키텍처 불일치  (0) 2025.05.09
Docker 명령어  (0) 2025.05.08
Docker: 컨테이너를 통한 효율적인 개발 환경 관리  (1) 2025.04.08

컨테이너 중지

# 특정 컨테이너 중지
docker stop 컨테이너ID_또는_이름

# 실행 중인 모든 컨테이너 중지
docker stop $(docker ps -q)

 

 

컨테이너 삭제
# 특정 컨테이너 삭제
docker rm 컨테이너ID_또는_이름

# 중지된 모든 컨테이너 삭제
docker rm $(docker ps -a -q)

# 컨테이너 강제 삭제 (실행 중인 컨테이너도 삭제)
docker rm -f 컨테이너ID_또는_이름
 
이미지 삭제
# 특정 이미지 삭제
docker rmi 이미지ID_또는_이름:태그

# 태그가 없는(dangling) 이미지 삭제
docker image prune

# 사용하지 않는 모든 이미지 삭제
docker image prune -a
 
한번에 정리
# 중지된 모든 컨테이너, 사용되지 않는 네트워크, 태그가 없는 이미지, 빌드 캐시 삭제
docker system prune

# 사용하지 않는 모든 리소스(볼륨 포함) 삭제
docker system prune -a --volumes

개발 작업 순서

개발용 컴퓨터에서 개발 → 테스트 성공 → 서버에 올림

 

배포: 서버(서버용 컴퓨터)에서 프로그램을 실행

 

개발용 컴퓨터와 서버용 컴퓨터에 이 프로그램을 돌릴 수 있는 환경이 동일해야 함

 


 

일반적인 개발 환경의 문제점

개발 환경을 하나의 집으로 비유했을 때, 이 집에는 Java, MySQL 같은 기술 스택이 설치된다는 것은 이것들이 입주자 처럼 생활 하는 것과 같음.

한 가지 서비스만 개발한다면 큰 문제가 없지만,

  • 서비스A는 Java 17버전이 필요한데, 서비스B는 Java 21버전을 필요로 함
  • 두 버전을 동시에 설치하면 충돌이 발생하고 복잡한 설정이 필요함
  • 다른 기술들도 버전 충돌 문제가 발생할 수 있음

결국 한 집에서 여러 프로젝트를 진행하면 입주자들이 함께 지내기 어려워짐.

 

 

가상화(Virtualization)의 한계

이 문제를 해결하기 위해 가상화 기술(VirtualBox, VMWare, Parallels 등)을 사용할 수 있음. 하나의 OS안에 또 다른 OS를 설치하여 서비스별로 분리된 환경을 제공함.

  • 컴퓨터 자원(CPU, 메모리)이 각 가상 환경마다 고정적으로 할당되어 비효율적
  • 각 가상 환경마다 별도의 OS가 필요해 저장 공간 낭비
  • OS기능들(부엌, 화장실 등)이 중복되어 자원 낭비

특히 성능이 중요한 서버 환경에서는 이러한 낭비가 더 큰 문제가 됨.

 

 

도커 컨테이너

도커는 컨테이너 개념을 통해 이 문제를 해결함.

  1. 격리된 작업 공간 : 컨테이너는 대저택 안의 업무 공간과 같음. 각 근무자가 자신만의 공간에서 일할 수 있음
  2. 자원 효율성 : 컨테이너들은 호스트 시스템 지원(CPU, 메모리)을 효율적으로 공유함. 필요한 만큼 사용하고 낭비를 줄임.
  3. 버전 충돌 방지 : 각 컨테이너는 독립적이므로 서로 다른 버전이 충돌없이 실행될 수 있음.
  4. 연결 가능 : 여러 컨테이너가 연결되어 복잡한 서비스를 구성할 수 있음.

 

또한 도커의 가장 큰 장점은 개발 환경에서 서버 환경으로의 배포를 간소화한다는 점.

  1.  선언적 설정 : 개발자는 컨테이너의 설계도(Dockerfile, Docker Compose)를 통해 설치 방법, 실행 방법, 연결 방법들을 명확히 정의할 수 있음 → 환경 일관성 유지
  2. 쉬운 배포 : 코드와 설계도를 서버에 전송하면 동일한 환경이 자동으로 구성됨

 

도커는 서로 다른 기술 스택과 버전들이 충돌 없이 공존할 수 있게 해주며,
개발 환경과 서버 환경의 일관성을 보장함.

 

 

 


 

[실습]

 

docker run -it node

 

로컬 환경에 'node'라는 이미지가 없다면, 자동으로 Docker Hub에서 최신 버전의 Node.js 이미지를 다운로드

이미지 다운로드 후 해당 이미지 기반으로 새로운 컨테이너를 생성하고 실행

 

docker ps

--name 이름 node 이런식으로 이름을 설정하지 않으면 자동으로 컨테이너 이름이 생성됨 (kind_bell)

 

docker exec -it kind_bell bash

'kind_bell' 컨테이너 안에서 bash shell을 실행

컨테이너 내부를 통해 가상의 리눅스 환경으로 들어감

 

 

Dockerfile: 이미지를 만들기 위한 설계도

 

🤔 node 이미지를 받았는데 나만의 이미지를 왜 또 만드냐?

컴퓨터에서 http-server란 프로그램을 돌리려면 Node.js만 설치되어 있어서는 안 됨. npm 등으로 http-server가 전역으로 깔려 있어야 함.
node 이미지는 아직 http-server가 없는 상태이기 때문에, 컨테이너로 실행할 때마다 매번 http-server를 받아줘야 함. (서비스를 돌릴 때마다 이런 모듈을 일일이 다운 받아야 함)
Node.js에다가 http-server까지 깔린 상태가 이미지로 있으면 컨테이너로 서비스를 실행하기 보다 수월해짐~!

 

 

Dockerfile

# 이 node 이미지에 덧붙여서 개조, 튜닝
FROM node:12.18.4

# 이미지 생성 과정에서 실행할 명령어
# Node.js가 깔린 node 이미지여서 npm 명령어 가능
# http-server 설치
RUN npm install -g http-server 

# 이미지 내에서 명령어를 실행할(현 위치로 잡을) 디렉토리 설정
WORKDIR /home/node/app

# 컨테이너 실행시 실행할 명령어
CMD ["http-server", "-p", "8080", "./public"]

# 이미지 생성 명령어 (현 파일과 같은 디렉토리에서)
# docker build -t {이미지명} .

# 컨테이너 생성 & 실행 명령어
# docker run --name {컨테이너명} -v $(pwd):/home/node/app -p 8080:8080 {이미지명}

 

RUN : 이미지를 생성하는 과정에서 실행되는 것, 이미지에서 컨테이너를 실행하는 시점에서는 이미 http-server가 설치.

CMD : 이미지로부터 컨테이너가 만들어져 가동될 때 바로 실행되는 명령어

 

 

1) 이미지 생성

docker build -t frontend-img .

frontend-img 이미지에는 이미 http-server가 깔린 상태

 

2) 컨테이너로 실행 (run)

docker run --name frontend-con -v $(pwd):/home/node/app -p 8080:8080 frontend-img

 

Volume: 컨테이너와 특정 폴더를 공유

 

 

 

FROM mysql:5.7

# 이미지 환경변수들 세팅
# 실전에서는 비밀번호 등을 이곳에 입력하지 말 것!
# 서버의 환경변수 등을 활용하세요.
ENV MYSQL_USER mysql_user
ENV MYSQL_PASSWORD mysql_password
ENV MYSQL_ROOT_PASSWORD mysql_root_password
ENV MYSQL_DATABASE visitlog

# 도커환경에서 컨테이너 생성시 스크립트를 실행하는 폴더로
# 미리 작성된 스크립트들을 이동
COPY ./scripts/ /docker-entrypoint-initdb.d/

 

COPY : RUN처럼 이미지를 생성하는 과정에서 해당 이미지 안에 특정 파일을 미리 넣어둠

'create_table.sql' , 'insert_data.sql' 파일들은 컨테이너 초기화 과정에 필요하기 때문에 COPY로 이미지 안에 미리 넣어두는 것

 

 

 

Docker Compose

여러 컨테이너를 정의하고 실행하기 위한 도구

version: '3'
services:
  database:
    # Dockerfile이 있는 위치
    build: ./database
    # 내부에서 개방할 포트 : 외부에서 접근할 포트
    ports:
      - "3306:3306"
  backend:
    build: ./backend
    # 연결할 외부 디렉토리 : 컨테이너 내 디렉토리
    volumes:
      - ./backend:/usr/src/app
    ports:
      - "5000:5000"
    # 환경변수 설정
    environment: 
      - DBHOST=database
  frontend:
    build: ./frontend
    # 연결할 외부 디렉토리 : 컨테이너 내 디렉토리
    volumes:
      - ./frontend:/home/node/app
    ports:
      - "8080:8080"

 

> 단일 명령어로 모든 컨테이너를 한 번에 빌드, 실행, 관리할 수 있게 해줌

 

 

'DevOps > Docker' 카테고리의 다른 글

Docker 배포 시 아키텍처 불일치  (0) 2025.05.09
Docker Hub에 이미지 올려서 배포해보기  (0) 2025.05.09
Docker 명령어  (0) 2025.05.08

+ Recent posts