본문 바로가기

IT 엔지니어/CLOUD

Docker file

[ CONTAINER 파일 및 디렉터리를 TAR 파일로 생성 ]

  • 실행 중이거나 중지된 Container 파일 시스템 전체를 .tar 파일로 저장
  • export
    • Image나 설정 없이 순수 파일 시스템만 저장하는 백업
    • Image처럼 다시 사용할 수 있게 만들기 위하 준비 단계
# docker export [옵션] [Container명/ID]

Image(httpd) 다운로드 후 Container 생성 및 실행을 해준다.

# docker pull httpd

# docker container create --name myweb1 -p 80:80 httpd

# docker container run -d --name myweb2 -p 80:80 httpd

test 디렉터리를 생성하고 진입해 .tar 파일을 저장할 준비를 한다.

# mkdir test

# cd test

Container 파일 시스템을 내보낸다. myweb1 이라는 Container의 파일 시스템을 myweb.tar로 저장해 준다.

(-o : 출력 파일의 이름 지정)

 

# docker container export myweb1 -o myweb1.tar

[ TAR 파일 압축 해제 ]

  • xvf
    • x : 압축 풀기
    • v : 진행되는 파일을 화면에 출력
    • f : 다음에 나오는 것이 파일명
  • -C : 디렉터리 경로 지정, 맨 마지막에 입력해야 함
# tar xvf [파일명].tar -C [압축해제경로]

docker export로 생성한 .tar 파일을 압축 해제한다. (

# mkdir /home/test

# tar xvf myweb1.tar -C /root/test/

dami 디렉터리 안에 압축이 정상적으로 풀려 있음

[ CONTAINER를 TAR로 백업 ]

<Container를 모두 강제 종료, 삭제 >

# docker rm -f $(docker ps -aq)

Container를 모두 삭제하고 다시 백업을 위해 재생성해 준다. 불필요한 Data 제거를 위해 test 디렉터리도 삭제해 줬다.

# docker rm -f $(docker ps -aq)

# docker run -d --name myweb -p 80:80 httpd

# rm -rf /root/test

[ CONTAINER를 .tar 파일로 EXPORT ]

# docker export [Container명] -o [파일명].tar

Container myweb1의 파일 시스템을 .tar 파일로 저장한다.

# docker export myweb1 -o myweb1.tar

[ .tar 파일로부터 IMAGE 복원 ]

  • 이름과 태그를 명시하면 Image 관리가 쉬워짐
# docker image import [파일명].tar
태그 없이
# docker image import [파일명].tar [Docker계정명/Image명]:[태그]
이름 및 태그 지정

.

 

# docker image import myweb1.tar

# docker image import myweb1.tar test/myweb2:1.0

이름 / 태그 X : <none>:<none>

 

이름 / 태그 지정

[ DOCKER IMAGE 자체를 .tar 파일로 저장 ]

  • Image 자체(계층 구조 포함)를 보존하므로 다른 Server로 옮겨도 그대로 사용 가능
# docker image save -o [파일명].tar [Image명(:태그)]

이때까지의 docker export/import는 Container를 tar로 저장하는 방식이었고, 이번에는 Image를 직접 저장 & 복원해 봤다. 이번 실습 Image는 ubuntu를 사용한다. ubuntu Image를 다운로드 받고, .tar 파일로 저장해 줬다.

# docker image pull ubuntu

# docker image save -o myubt.tar ubuntu

[ 저장한 .tar 파일을 IMAGE로 복원 ]

# docker image load -i [파일명].tar

 

# docker rmi ubuntu

# docker image load -i myubt.tar

# docker images

 

 

Image로 복원된 .tar 파일 확인 가능

 

 

🔍 예시 흐름으로 보기

① 컨테이너 파일 백업 & 복원 (운영 중 데이터까지)

docker export mycontainer.tar > container_backup

docker export -o myweb myweb.tar

tar -xvf myweb.tar [test]

docker import container.tar mynewimage

docker import backup.tar > [name] / 현재 디렉에 생성 -> 결과만 출력 / docker images에서 확인 가능

docker images 확인

  • 컨테이너 상태만 저장됨 (설정, 볼륨, 네트워크 등 X)

② 이미지 자체 백업 & 복원 (설정 포함된 정식 이미지)

docker image save myimage:latest > image_backup.tar

docker save -o test.tar test
현재 디렉에 저장

docker load -i test.tar test

docker image load < image_backup.tar

  • 이미지 자체 완전 복원 (태그 포함)

 

 

[ DOCKER : save/load vs export/import ]

export / import
save / load
대상
CONTAINER
IMAGE
계층 / 설정 보존
X
O
목적
Container 상태 저장
Image 이동, 백업

DOCKERFILE

FROM [Image명]
베이스 Image 설정
RUN [셸 명령어]
Container 안에서 실행할 명령어 설정
ENV [키]=[값]
환경 변수 내용 설정
CMD [실행할 명령어 / 옵션]
Container 실행될 때 자동으로 실행할 프로세스 지정

[ DOCKER FILE을 이용한 IMAGE 생성 ]

< Index 파일 작성 >

작업할 디렉터리(/test/public_html)를 생성하고 index.html 파일을 작성했다.

# mkdir /test/public_html

# vi /test/public_html/index.html

< DockerFile 작성 >

  • COPY
    • HTML 파일을 Container 내부 Web 루트 디렉터리에 복사
    • DockerFile COPY 명령은 Dockerile이 있는 디렉터리를 기준으로 경로를 해석함 (절대 경로 아님)

httpd 기반으로 Image를 생성했다. test/public_html/index.html 파일을 Container 내부 /usr/local/apache2/htdocs/index.html로 복사해 주는 DockerFile을 작성해 줬다. 현재 COPY는 /test 디렉터리를 기준으로 경로를 해석하기 때문에 /test는 입력하지 않는다. (DockerFile 하위 디렉터리부터 입력!)

# vi /test/Dockerfile

< DockerFile로 Image Build >

  • Build Context
    • Docker가 Build 시 참고하는 기준 디렉터리 (DockerFile에서 사용하는 경로)
# docker image build -t [Image명] [DockerFile디렉터리]
해당 디렉터리에서 Dockerfile 및 모든 파일을 사용해 Build
# docker image build -t [Image명] -f [DockerFile경로] [Context디렉터리]
Dockerfile과 Context 경로가 다를 때 사용
build [디렉터리]
-f [DockerFile] [Context]
DockerFile 위치
디렉터리 안
어디든 가능
Context 위치
DockerFile 위치와 동일
원하는 위치 지정 가능

Image 이름을 myweb1으로 지정해 DockerFile이 위치한 디렉터리를 Build 컨텍스트로 사용했다. Build 후 정상적으로 생성된 myweb1 Image를 확인했다.

# cd /test

# docker image build -t myweb1 /test

< Web Server 실행 및 접속 TEST >

Test를 위해 생성한 Image로 Web Server(Container)를 실행 후 브라우저에서 접속했다. 정상적으로 index 파일이 출력된 화면이다.

# docker run -d -p 8080:80 --name webtest myweb1

httpd://192.168.10.100:8080


IMAGE BUILD 방식

: SINGLE STAGE & MULTI STAGE

[ SINGLE STAGE BUILD ]

  • Dockerfile에서 모든 작업(소스 복사, Build, 실행파일 포함)을 한 Docker 안, 한 번에 처리하는 방식

[ MULTI STAGE BUILD ]

  • Dockerfile 내에 여러 단계(stage)를 나눠서, 중간 단계에서만 필요한 build 도구 등은 최종 Image에 포함하지 않는 방식
    • Build용, 실행용 - Build는 도구 많은 Container에서 하고, 실행은 가볍게!

[ Go 언어 설치 ]

# dnf -y install golang-bin

< Go 소스코드 작성 >

Go 언어를 다운로드 받고 기본적인 "Hello World" 프로그램을 작성해 준다. 코드를 실행하면 Hello Docker를 화면에 출력하도록 작성했다.

# vi /test/main.go

< Go 코드 실행 >

Go 코드를 실행시켜본다. 파일이 있는 디렉터리에서만 실행된다.

# go run main.go

< 실행 파일 생성 >

main.go를 실행 가능한 바이너리 파일로 컴파일해 준다. main은 생성된 실행파일이고, main.go는 원본 소스 파일이다.

# go build main.go

< 실행 >

작성한 Go 코드가 컴파일되어 성공적으로 실행된다. 이 과정은 이 코드를 Docker Image로 만들어서 Container 안에서 Hello Docker를 출력하게 만들기 위해서 진행했다. 즉, Multi Stage Build로 Go 앱 배포할 때 가장 기초적인 준비 작업!

# ./main

이제 Docker로 Go 애플리케이션 Image를 만들 때, Single Stage vs Multi Stage 방식의 차이를 직접 실행하며 확인할 것이다. 이 두 가지 방식으로 Go 코드(main.go)를 Build 해서 실행 파일(hello)을 만들고 Docker Image 안에 넣어서 실행되게 할 것이다. → Single Build = Dockerfile1 / Multi = Dockerfile2

< Single Stage Build - Dockerfile1 >

우선 Go 프로그램을 Docker Image로 만들었다. syntax highlighting(자동 문법 하이라이팅)을 위해 :set filetype=dockerfile로 인식 시켜줬다.

# vi /test/Dockerfile1

# cd /test

< Build >

Image 이름을 singlestae으로 방금 만든 Dockerfile1을 지정해 Build 해준다.

# docker image build -t singlestage -f Dockerfile1 .

< Multi Stage Build - Dockerfile2 >

# vi /test/Dockerfile2

< Build >

# vi /test/Dockerfile2

# docker image build -t multistage -f Dockerfile2 .

< 결과 : Single Stage vs Multi Stage >

결과적으로 singlestage는 모든 게 들어간 무거운 Image가 생성되었고, multistage는 최적화된 Image가 생성되었다. 베이스 이미지와 포함된 항목으로 인해 최종 용량이 차이가 난다. 즉, Multi Stage Build 시 필요한 실행파일만 따로 빼서 작은 Image를 생성할 수 있는 것이다. 최종 실행만 필요한 환경에는 Multi가 유리하다.


DOCKERFILE 명령 차이점

: RUN vs CMD vs ENTRYPOINT

[ RUN & CMD ]

  • RUN
    • Image를 Build 할 때 실행됨
    • Image 안에 어떤 파일을 설치하거나 셋업 할 때 사용
    • 실행 결과가 Image에 영구 반영됨 (레이어 생성됨)
    • ex) 소프트웨어 설치, 파일 복사, 디렉터리 생성 등
  • CMD
    • Cintainer가 시작(run) 될 때 실행됨
    • Image 안에 들어있는 기본 실행 명령 설정
    • 사용자가 run 명령 시 명령어를 지정하면 CMD는 무시됨
    • ex) Container 시작 시 자동으로 Web Server 실행 등
RUN
CMD
실행 시점
Image Build 시
Container 실행 시
용도
설치, 환경 구성
실행 명령 설정
실행 결과
Image에 저장됨 (레이어 생성)
Container 시작 시 실행됨 (영구 저장 X)

[ CMD & CMD ]

  • CMD
    • Container 실행 시 기본값으로 실행될 명령
    • Container 실행 시 명령을 따로 주면 → CMD 무시됨
  • ENTRYPOINT
    • Conitainer가 실행될 때 반드시 실행되는 명령
    • run 시 전달하는 인자는 ENTRYPOING의 인자로 추가됨
  • CMD는 기본값(덮어쓸 수 있음), ENTRYPOINT는 무조건 실행
CMD
ENTRYPOINT
기본 실행 명령
O
O
run 시 명령으로 대체 가능
O
X (무시되지 않음)
유연성
↓ (단단한 실행 방식)
자주 쓰는 경우
디폴트 실행 명령
절대 고정된 실행 명령 필요할 때

[ RUN & CMD & ENTRYPOINT ]

RUN
Image 만들 때 설치 / 설정용
CMD
기본 실행 명령 (바꿀 수 있음)
ENTRYPOINT
고정된 실행 명령 (바꿀 수 없음)

RUN 명령어를 다양한 방식으로 실행해 보고, 실제로 어떻게 실행되고 레이어가 생성되는지 확인해 볼 것이다. 실습을 위해 Dockerfile3 파일을 만든 후 내용을 입력해 줬다.

# vi /test/Dockerfile3

작성한 Dockerfile3을 기반으로 Image를 Build 해줬다.

# docker image build -t build1 --no-cache --progress plain -f Dockerfile3.

[ IMAGE 생성 과정 LAYER 단위로 출력 ]

  • 단순 기록이 아니라 Image 최적화, 디버깅, 용량을 줄이기 위한 단서를 주는 도구
# docker history [Image명/ID]

Dockerfile3에 작성한 각 RUN 명령들이 Image에 별도의 레이어로 기록되어 출력됐다. Dockerfile3에 작성한 3가지 RUN 명령들이 레이어로 정상 등록되어 있는 것을 확인했다.

# docker history build1


ENTRYPOINT와 CMD를 활용한

CONTAINER 실행 명령 제어

Dockerfile에서 ENTRYPOINT와 CMD를 함께 설정해서 CONTAINER 실행 시 top 명령어를 자동으로 동작하게 설정을 해 볼 거다. 특정 옵션(-d, 10)을 CMD로 설정해서 동작을 제어해 볼 것이다.

< Dockerfile 작성 >

우선 Ubuntu Image를 기반으로, Container가 실행되면 자동으로 top -d 10 명령이 10초 간격으로 실행되도록 Dockerfile을 작성해 준다.

# vi /test/Dockerfile4

< Image Build >

# docker image build -t [Image명] -f [Dockerfile명] [Context경로]

Dockerfile4를 기반으로 myos 라는 Image를 생성해 준다.

# docker image build -t myos . -f Dockerfile4

COMMAND에 top = ENTRYPOINT 잘 작동함

PID : 1 = Container의 주 프로세스로 실행됨

# docker container run -it --name top1 myos


실습

[ 사용자 계정 실습 ]

  • Container 안에서 새 User(user1)를 생성하고, 그 User로 명령 실행

< Dockerfile 작성 >

# vi /test/Dockerfile5

FROM centos:8

RUN ["useradd", "user1"]

RUN ["whoami"]

RUN ["id"]

USER user1

RUN ["whoami"]

RUN ["id"]

< Build >

# docker image build -t user7 .

# docker image build --no-cache --progress plain -t user8 .

< 결과 >

USER 명령어를 쓰면 root에서 user1로 자동 변경됨

[ 웹 페이지 & 압축파일 복사 실습 ]

  • Image 안에 html 파일과 tar.gz 압축 파일을 같이 넣고, nginx 띄우기

< Dockerfile 작성 >

# vi /test/Dockerfile6

FROM ubuntu:latest

RUN apt-get update && apt-get -y upgrade

RUN apt-get -y install nginx

COPY index.html /var/www/html

COPY index.tar.gz /var/www/html

ADD add.tar.gz /var/www/html

CMD ["nginx", "-g", "daemon off;"]

< 파일 생성 >

# tar -czf index.tar.gz index.html

# cp index.html index2.html

# tar -czf add.tar.gz index2.html

< Build >

add 라는 이름으로 Image 생성됨

# docker image build -t add .

< 결과 >

add로 Image Container 실행해서 /var/www/html 안에 있는 파일 목록 확인

# docker container run --rm add ls /var/www/html

index.html

index.nginx-debian.html

 

'IT 엔지니어 > CLOUD' 카테고리의 다른 글

Docker -1  (0) 2025.05.13
Docker Network 심화  (0) 2025.05.12
Docker Network  (0) 2025.05.11
Docker network  (0) 2025.05.10
Docker DB  (2) 2025.05.09