20220510 필기노트

강재민·2022년 5월 10일
1

필기노트

목록 보기
4/23

수업내용 요약


Docker 이미지 빌드

방법

  • docker commit 명령
  • Dockerfile

명령으로 이미지 생성

docker diff

docker diff <CONTAINER>

기준 이미지 <-> 컨테이너 차이

  • A: Add
  • C: Change
  • D: Delete

docker commit

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

CMD 변경

docker commit -c "CMD XXX" CONTAINER [REPOSITORY[:TAG]]

ExposedPort 변경

docker commit -c "EXPOSE PORT/PROTOCOL" CONTAINER [REPOSITORY[:TAG]]

ExposedPort는 실제 작동여부와 상관 X

CMD /usr/sbin/apache2ctl -D FOREGROUND

/bin/sh -c /usr/sbin/apache2ctl -D FOREGROUND

docker cp

컨테이너 -> 도커 호스트

docker cp CONTAINER:SRC_PATH DEST_PATH

도커 호스트 -> 컨테이너

docker cp SRC_PATH CONTAINER:DEST_PATH

/bin/sh -c /usr/sbin/apache2ctl -DFOREGROUND

이미지 레이어

레이어를 가지는 이유? 저장소 및 네트워크 전송 효율성 높임

httpd:latest

sha256:9c1b6dd6c1e6be9fdd2b1987783824670d3b0dd7ae8ad6f57dc3cea5739ac71e sha256:1d1a2486e901871ad1257512d588eebb30ae0605d8353abb6635e2d313b2187c sha256:ec02eb7f3cf4dd78bc518d3a8ccf57f57336ceacb9638303891787ff2ec2e96f sha256:67bb571b5bd2b65cbdf2c93c6f9dc8e89414055dd7444df617b23466996f3be7 sha256:e83f42350a11889083536c5af330dcf15fd3624f8e956f4086e1f0cfb07ff246

myhttpd:latest

sha256:9c1b6dd6c1e6be9fdd2b1987783824670d3b0dd7ae8ad6f57dc3cea5739ac71e sha256:1d1a2486e901871ad1257512d588eebb30ae0605d8353abb6635e2d313b2187c sha256:ec02eb7f3cf4dd78bc518d3a8ccf57f57336ceacb9638303891787ff2ec2e96f sha256:67bb571b5bd2b65cbdf2c93c6f9dc8e89414055dd7444df617b23466996f3be7 sha256:e83f42350a11889083536c5af330dcf15fd3624f8e956f4086e1f0cfb07ff246 sha256:4b8c655a2e61d6f017f3a5cc103fe6bbb6f71bba663085fdae697861dd57695a

myhttpd:p8080

sha256:9c1b6dd6c1e6be9fdd2b1987783824670d3b0dd7ae8ad6f57dc3cea5739ac71e sha256:1d1a2486e901871ad1257512d588eebb30ae0605d8353abb6635e2d313b2187c sha256:ec02eb7f3cf4dd78bc518d3a8ccf57f57336ceacb9638303891787ff2ec2e96f sha256:67bb571b5bd2b65cbdf2c93c6f9dc8e89414055dd7444df617b23466996f3be7 sha256:e83f42350a11889083536c5af330dcf15fd3624f8e956f4086e1f0cfb07ff246 sha256:4b8c655a2e61d6f017f3a5cc103fe6bbb6f71bba663085fdae697861dd57695a sha256:fffe7ea283ae8867d740e17f619c4db845cb0d75fc655809185e582601786521

docker history

이미지 생성 로그 확인

docker history <IMAGE>

docker export

컨테이너 -> 아카이브

docker export <CONTAINER> -o <TARFILE>

docker import

아카이브 -> 이미지

docker import <TARFILE> <IMAGE>:<TAG>

1개의 레이어로 가져오기

Dockerfile 이미지 생성

FROM

Base Image

FROM <image>
FROM <image>[:<tag>]
FROM <image>[@<digest>]

RUN

빌드시 실행할 명령

Shell Form

RUN yum install httpd

=> /bin/sh -c yum install httpd

Exec Form

RUN ["yum", "install", "httpd"]

=> exec yum install httpd

exec는 명령 X

CMD

기본 실행 어플리케이션

Shell Form

CMD /usr/sbin/httpd -DFOREGROUND

=> /bin/sh -c yum install httpd

Exec Form(선호)

CMD ["/usr/sbin/httpd", "-DFOREGROUND"]

EXPOSE

외부에 노출할 포트 및 프로토콜

EXPOSE <PORT>/<PROTOCOL>

ENV

쉘 환경 변수

ENV MY_NAME="John Doe"
ENV MY_DOG=Rex\ The\ Dog
ENV MY_CAT=fluffy

ADD/COPY

도커 호스트 -> 컨테이너 파일 복사

ADD <SRC> <DEST>
COPY <SRC> <DEST>

ADD는 SRC로 URL 지정 가능

ENTRYPOINT

CMD의 명령으로 사용

ENTRYPOINTCMDResult
XX허용X
Xabcabc
xyzXxyz
xyzabcxyz abc

VOLUME

자동으로 마운트할 볼륨 마운트 포인트 지정

VOLUME /myvol

WORKDIR

작업 디렉토리
RUN, CMD, ENTRYPOINT, ADD, COPY에 영향을 미침

WORKDIR /usr/local

레이어

RUN, ADD, COPY 레이어를 만듦

예제

mkdir -p ~/image-build/myweb
cd ~/image-build/myweb

Dockerfile

FROM centos:7
RUN yum install -y httpd
ADD index.html /var/www/html/index.html
CMD ["/usr/sbin/httpd", "-DFOREGROUND" ]
EXPOSE 80/tcp

index.html

hello dockerfile
docker build -t myweb:centos .

Linux Timezone 설정

/etc/localtime 파일이 가리키고 있는 파일이 시간대

시간대
/usr/share/zoneinfo/*

sudo ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime
sudo timedatectl

ubuntu 20.04/focal 이미지 부터 시간대가 설정되어 있지 않음
우회: ENV DEBIAN_FRONTEND=noninteractive


필기 노트 시작


Docker 이미지 빌드


docker commit

시작하기 전에 컨테이너와 볼륨을 비우고

docker run -d httpd
docker ps
docker exec -it 3a bash
pwd
cd htdocs/
ls
cat index.html
echo <h1> hello world! </h1>" > index.html
cat index.html
exit
docker ps
docker diff 3a		#리눅스의 diff명렁어와 같음 지금과 초기 이미지의 차이를 보여줌 c는 change a는 add d는 delete를 의미함
### httpd.pid는 프로세스 id가 몇번인지 기록하는 것이라 항상 바뀌게 됨 그리고 상위 디렉토리들도 다 바뀌게되고 history는 추가가 되는것임 이런 추가 변경 사항들을 diff 명령어를 통해 알 수 있다.
docker exec -it 3a bash
cd /root/
ls
cd icons/
rm a.gif
exit
docker diff 3a
### 하면 D라고 해서 /usr/local/apache2/icons/a.gif 부분이 제거되었다고 알려준다.
docker ps
docker commit 3a --help		#생성할 이름을 지정
docker commit sad_bose myhttpd
docker images				#myhttpd라는 이미지가 생성이 된것을 확인
docker run -d -p 80:80 myhttpd
docker ps
### 크롬창에 가서 192.168.100.100에 접속해보면 hello world! 라는 바뀐 내용으로 나오게 된다

실습내용 서비스포트를 8080으로 변경해서 이미지를 만들어보고 테스트를 해보아라

docker cp --help

docker cp e1

docker sed를 이용해서 변경할 수 도 있음

sed -i 's/Listen 80/Listen 8080/g' httpd.conf		#대소문자 구분

docker commit --help

예제
우분투 이미지 아파치 이미지 만들기
docker commit -c "CMD XXX" ab myhttpd

docker pull centos:7
docker run -itd centos:7
docker exec -it c2 bash
yum install -y httpd


여기보면

systemctl start하면 정확하게

이부분이 시작된다.
Reload와 stop은

그래서 systemctl start하지않고

sudo /usr/sbin/httpd -DFOREGROUND &

명령어를 해주면 된다

docker exec -it c2 bash
cd /var/www/html/
ls
echo "hello centos" > index.html
cat index.html
docker commit -c "CMD /usr/sbin/httpd -DFOREGROUND" c2 myapache:v1
docker images
docker run -d -p 80:80 myapache:v1
docker ps
### 크롬창에 192.168.100.100 하면 hello centos가 나오게 된다.

이번에는 우분투

docker run -itd ubuntu:focal
docker exec -it cb bash
apt update
apt install apache2
cd /usr/sbun/
ls
apache2ctl		#을 나중에 실행시켜줘야함
cd /var/www/html
echo "<h1> hello ubuntu </h1>" > index.html
exit
docker ps
docker commit -c "CMD /usr/sbin/apache2ctl -D FOREGROUND" cd myweb:ubuntu
docker run -d -p 80:80 myweb:ubuntu
docker ps
docker image inspect myweb/ubuntu
###보면


뒤에 명령어가 shell에 의해서 실행이 된다라고만 일단 이해를 하고 넘어가자

sh -c ls
bash -c /usr/bin/ls

이렇게 순차적으로 bash

이부분은 사용자에게 제공할 정보이지 실제 작동하는 내용과는 전혀 의미가 없다고한다. 다만 필요하다면 세팅할 수는 있음


이렇게 세팅을 할 수 있음


layer

우리가 만든 이미지의 레이어와
원본이미지의 레이어 차이를 확인해보자

첫 번째 원본 이미지는 5개의 층으로 만들어져있다.
각 레이어들은 모두 read-only이다 그러면 컨테이너는 이 레이어들 가장 바깥쪽에 read-write층을 만들어서 여기에 index.html을 만들었고 commit을 할 때도 레이어가 하나 추가가 되는 구조이다

docker image history 또는
docker history를 이용해서

docker history httpd
### missing은 내 로컬영역에 로그가 없다는 것이고
### 뒤에는 그때 사용했던 명령어들이다
### SIZE가 있다는건 무언가 변경되거나 추가되었다는것이고 없다면 파일이 추가된것은 아니다라고하는것이고
### COMMENT는 commit을 할 때 추가 할 수 있음

comment 추가



history를 비교해보면 어떤 변경사항이 이미지에 있었는지 확인이 가능하다.

이번에는 centos를 살펴보면


이렇게 yum으로 패키지가 설치된 것임

이번에는 ubuntu를 살펴보면

이런식으로 레이어가 점점 쌓이면서 만들어가는것이다.

docker run -itd ubuntu:focal
echo "hello a" > a.txt
echo "hello b" > b.txt
docker cp a.txt d3:/root
docker diff d3
docker commit d3 ubuntu:focal-v1
docker run -itd ubuntu:focal-v1
docker cp b.txt 7c:/root
docker diff 7c
docker images | grep ubuntu

정리해보면..


docker save



json으로 끝나는 파일을 열어보면 docker inspect 로 볼 수 있는 정보가 나온다.

제일 밑에 있는 레이어를 확인 가능 하고


각각의 레이어마다 어떤 정보가 들어있었는지 정확히 확인이 가능하다.

docker info


overlay2는 파일시스템을 의미한다.
예전에는 aufs라는 파일시스템도 있었다. advanced union file system
이것은 ufs 파일시스템으로부터 파생되어 나온것이고
ufs는 Union FS이다

이렇게 3개의 블록을 하나의 블록처럼 사용할 수 있게 해주는 것임
그 시작점이 ufs이다

현재는 모든 리눅스들이 overlay2 파일시스템을 사용하고있다.

이렇게 굳이 레이어를 나누어서 다시 합치는 이유는 이미 있는 레이어는 받지 않아도 되는 것이라는 것이다. base 이미지들은 몇100 메가바이트 하는데 이런 것들은 있으면 굳이 또 받을 필요가 없기 때문에 이런것을 레이어로 공유해서 재사용 가능하다.

그래서 전략적으로 레이어를 어떻게 구분할지 생각해봐야한다.

질문
강사님 그러면 기존이미지의 특정 내용을 제거하고 commit을 하고 다음에 새로 commit한 이미지를 실행시켰다고 했을 때에도 기존 레이어를 변경시킨것은 아닌게 되는건가요?

결국 최소한으로 만들어야하는 원칙이 있어야 다시 지우는 불상사가 생기지 않는다.

질문사항
httpd-foreground가 무엇인가요?
docker run -d httpd
docker ps

which httpd-foreground
cd /usr/local/bin/
cat httpd-foreground
cat /usr/local/apache2/logs/httpd.pid

이 부분이 실행되는 것이다



이렇게 실행되는 것이다.
CMD보다 ENTRYPOINT가 먼저 실행된다.

docker export --help

docker save --help
docker export 39 -o httpd.tar
ls
mkdir httpd
tar xf httpd.tar -C httpd
cd httpd
ls

이렇게 아카이브해서 풀어서 확인하는 방법도 있다
그리고 이렇게 tar파일을 이미지로 가져오는것도 가능하다.

docker import --help
docker ps
docker import httpd.tar a:v1
docker image ls

다만 이렇게하면 이미지의 레이어가 하나가된다.


Dockerfile 이미지 생성

https://docs.docker.com/engine/reference/builder/
도커파일로 이미지를 만드는 방법
지금까지는 docker run 하고 exec로 들어가서 yum으로 작업하고 했지만 이런것들을 Dockerfile로 할 수 있음

현재 디렉토리에 Dockerfile이 있어야하고 있으면 docker build를 통해 세팅을 하는것임

docker build .

.잊지말고 붙여주기
/를 해보리면 루트에있는 모든 내용을 올려버리므로 주의하기


이런 형태로 이루어져있음


FROM


FROM은 베이스 이미지를 지정하는것
우리는 x86만 사용하기 때문에 굳이 지정할 필요는 없음
ASname은 별칭
결국 남는 항목인 image만 지정을 해주면 됨


RUN

RUN은 커맨드를 실행하는 부분이다.
이미지를 빌드하는 중에 실행할 명령어를 지정하는 부분
shell form 이냐 exec form이냐가 중요함

이게 shellform

그리고 exec form

shell에서 실행했느냐 안했느냐의 차이로 인지를 하면 된다.

대괄호[]형태는 exec 형태로 쉘을 실행하지않고 명령어를 사용하는형태임.

정리해보면 다음과 같다.


쉘을 실행하지않고 그 자체 함수로 실행한다는... 그런 뜻이라고 하긴함
다만 결국 쉘폼이나 exec폼이나 차이는 크게 없다.


CMD

CMD는..

CMD에서는 쉘폼과 exec폼의 차이가 극명하게 난다.


이것은 exec 폼이다
쉘폼은 무조건 bin/sh 이런 형태로 되어있음

docker run -d httpd
docker ps
docker stop 85
docker start 85
docker ps
time docker stop 85
docker inspect 85
docker ps -a
docker run -d myweb:ubuntu
docker ps
docker stop ad
docker start ad
time docker stop ad
docker inspect ad
docker ps -a
kill -l		#15번 시그널은??
SIGTERM





137-128=9

shell은 자신의 하위 프로세스에게 명령어를 전달하지 않는다.
그래서 우리는 항상 stop을하면 비정상종료만 겪게된다.
이때 10초의 딜레이가 걸리는건데 이것또한 당연히 오류이다.


LABEL

LABEL은 그냥 키값쌍의 설명역할


MAINTAINER

MAINTAINER는 이제 더이상 사용하지 않음


EXPOSE

EXPOSE 는 열어놓을 포트 기본값은 TCP임 당연히 4계층


ENV

ENV 는 환경변수


ADD, COPY

ADD와 COPY는 동일하게 사용가능하다.
다만 차이는 ADD는 주소를 지정할 수 있다.

단, COPY는 안된다 COPY는 파일간에만 가능


방향은 항상 호스트에서 컨테이너로만


ENTRYPOINT

ENTRYPOINT 어플리케이션을 실행하기 위한 구성임

가운데는 쉘방식을 쓰는거라 제외
맨 아래도 쉘방식이라 제외
순서는 엔트리포인트 먼저 그다음 CMD

그림을 잘 이해해보면 됨
결국 엔트리포인트만, CMD만, 아니면 둘 다 있는 경우 이렇게만 생각하면 되는 쉬운 내용임.
간단하게 표로 정리하면..

예시는 다음과같음

만약 교체하고싶으면

entrypoint는 명령어 cmd는 옵션 또는 argument


VOLUME

VOLUME 은 볼륨을 생성하거나 마운트할 때 사용


USER

USER 는 entrypoint 와 cmd를 사용할 계정을 지정할 수 있다.
만약에 지정하지 않으면 기본은 root임

컨테이너는 모든 내용을 root로만 작업하고 있는것은 보안에 문제가 될 소지가 있다


WORKDIR

WORKDIR 은 명령어를 실행할 때 상대경로로 실행하게되면 WORDDIR이 중요하게 되고 COPY할 때에도 경로를 상대경로로 쓴다면 작업 디렉토리를 의미하는 WORKDIR이 중요해진다.


이거는 편의상 하는거고 가능하면 절대경로를 사용하는 것을 권장한다.

ARG는 도커 파일 내부에서 사용할 변수이다.
변수명 - 기본값형식임

이렇게 사용가능한데 그렇게 많이 사용하지는 않다.


ONBUILD

ONBUILD 뒤에 INSTRUCTION을 쓰는데 [RUN CMD ARG] 이런게 들어가고 빌드를 할 때 마다 실행할 명령어를 의미한다. 거의 잘 사용되어지지는 않다.


STOPSIGNAL

STOPSIGNAL 이거는 SIGTERM이 생략되어있는거고 어떤 특정 시그널을 받으면 중지시켜라 그런 기능인데 잘 사용되지않음


HEALTHCHECK

HEALTHCHECK 는

이런 curl을 해보고 안되면 재시작하게끔 하는 기능도있긴한데 잘 쓰지는 않다 도커에서만 쓰고 쿠버네티스에서는 잘 사용하지는 않음


SHELL

SHELL은 CMD,RUN,ENTRYPOINT에서 SHELL FORM을 쓸 때 실행할 명령을 지정할 수 있긴한데 잘 안씀


요약정리 및 예제

docker run -itd ubuntu					#FROM
docker exec abc apt install httpd		#RUN
docker cp index.html abc:/var/www/html	#ADD,COPY
docker commit -c CMD -c EXPOSE			#COM,EXPOSE
mkdir image-build
cd image-build
echo "hello dockerfile" > index.html
vi Dockerfile

FROM centos:7
RUN yum install -y httpd
ADD index.html /var/www/html/index.html
CMD ["/usr/sbin/httpd","-DFOREGROUND"]
EXPOSE 80/TCP

이렇게하면 순서대로 잘 실행됨


ubuntu 예제

ubuntu 이미지로 작업을 해보자

FROM ubuntu:focal
RUN apt update
RUN apt install -y apache2		#RUN명령어를 내릴 때 마다 레이어가 생성된다.

###그래서 각각의 레이어로 구성하기 싫다면
RUN apt update; apt install -y apache2		#대화형식이 아니기 때문에 -y옵션을 꼭 붙여서 모든 대화 형태를 차단해주어야한다. 
###이렇게 할 수 있음
EXPOSE 80/tcp
CMD ["/usr/sbin/apache2ctl", "-DFOREGROUND"]

이렇게 구성해서 실행을 하면..

질문
그럼 아까 우분투 시간설정할 때 서울로 설정하는거는 어떻게 할 수 있을까요..
sudo timedatectl 로 시간대를 확인할 수 있는데, 우분투 이미지에는 time zone이 설정되어있지 않았다
centos이미지는 기본적으로 time zone을 설정하지않으면 기본적으로 UTC로 설정되어있는데 redhat만 해당함
ubuntu의 docker 이미지는 시간대가 설정되어있지 않다 그래서 이것을 어떻게 할 것인지 물어보는데 이게 대화형식으로 작동하다보니 이 걸리게되었다.
그래서 간단하게 팁을 드리면
ENV DEBIAN_FRONTEND=noninteractive
라는 환경변수 설정을 해주면 됨
그러면 기본값으로 그냥 넘어가게된다.
이건 정상적인 방법은 아니다.

우분투는 기본적으로 mirror가 설정되어있지않아서 유럽으로 갔다가 오는거라 느림

RUN
ADD
COPY
를 만날 때마다 다시 커밋하는 과정을 반복하게됨


Linux Timezone 설정

/etc/localtime 파일이 가리키고 있는 파일이 시간대

ls -l /etc/localtime
cd /usr/share/zoneinfo
ls
cd Asia
ls
ls Seoul			#이것을 심볼릭 링크를 걸어주어야한다.
sudo ln -sf /usr/share/zoneinfo/Asia/seoul /etc/localtime			#f으로 덮어 쓰는 옵션
ls -l /etc/localtime
sudo timedatectl

※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
이 내용을 이용해서 우분투 이미지를 만드는게 숙제
※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※

ubuntu 20.04/focal 이미지 부터 시간대가 설정되어있지 않음
그래서 우회하는 방법이 있지만 해결방법은 아님 그러므로 이 부분을 해결해보기

docker images
docker run -d -p 80:80 myweb:ubuntu
### 크롬창에 192.168.100.100

내일 수업할 내용

간단하게 파이썬 코드를 짜서 그 파이썬 코드를 실행할 수 있는 이미지를 만들어볼 예정이다.
장고 node.js 등등..
bullseye 데비안
buster 데비안
slim은 주요 라이브러리를 빼놓은 것들
apline 이야가도 내일 할것이고 각 이미지들의 용량을 비교해보기

https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
이미지를 가지고 작업할 내용을 공부할 예정 미리 한 번 보면 좋음

0개의 댓글