방법
docker commit
명령docker diff
docker diff <CONTAINER>
기준 이미지 <-> 컨테이너 차이
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개의 레이어로 가져오기
Base Image
FROM <image>
FROM <image>[:<tag>]
FROM <image>[@<digest>]
빌드시 실행할 명령
Shell Form
RUN yum install httpd
=> /bin/sh -c yum install httpd
Exec Form
RUN ["yum", "install", "httpd"]
=> exec yum install httpd
exec는 명령 X
기본 실행 어플리케이션
Shell Form
CMD /usr/sbin/httpd -DFOREGROUND
=> /bin/sh -c yum install httpd
Exec Form(선호)
CMD ["/usr/sbin/httpd", "-DFOREGROUND"]
외부에 노출할 포트 및 프로토콜
EXPOSE <PORT>/<PROTOCOL>
쉘 환경 변수
ENV MY_NAME="John Doe"
ENV MY_DOG=Rex\ The\ Dog
ENV MY_CAT=fluffy
도커 호스트 -> 컨테이너 파일 복사
ADD <SRC> <DEST>
COPY <SRC> <DEST>
ADD는 SRC로 URL 지정 가능
CMD의 명령으로 사용
ENTRYPOINT | CMD | Result |
---|---|---|
X | X | 허용X |
X | abc | abc |
xyz | X | xyz |
xyz | abc | xyz abc |
자동으로 마운트할 볼륨 마운트 포인트 지정
VOLUME /myvol
작업 디렉토리
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 .
/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 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
이부분은 사용자에게 제공할 정보이지 실제 작동하는 내용과는 전혀 의미가 없다고한다. 다만 필요하다면 세팅할 수는 있음
이렇게 세팅을 할 수 있음
우리가 만든 이미지의 레이어와
원본이미지의 레이어 차이를 확인해보자
첫 번째 원본 이미지는 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
정리해보면..
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 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
다만 이렇게하면 이미지의 레이어가 하나가된다.
https://docs.docker.com/engine/reference/builder/
도커파일로 이미지를 만드는 방법
지금까지는 docker run 하고 exec로 들어가서 yum으로 작업하고 했지만 이런것들을 Dockerfile로 할 수 있음
현재 디렉토리에 Dockerfile이 있어야하고 있으면 docker build를 통해 세팅을 하는것임
docker build .
.
잊지말고 붙여주기
/를 해보리면 루트에있는 모든 내용을 올려버리므로 주의하기
이런 형태로 이루어져있음
FROM은 베이스 이미지를 지정하는것
우리는 x86만 사용하기 때문에 굳이 지정할 필요는 없음
ASname은 별칭
결국 남는 항목인 image만 지정을 해주면 됨
RUN은 커맨드를 실행하는 부분이다.
이미지를 빌드하는 중에 실행할 명령어를 지정하는 부분
shell form
이냐 exec form
이냐가 중요함
이게 shellform
그리고 exec form
은
shell에서 실행했느냐 안했느냐의 차이로 인지를 하면 된다.
대괄호[]형태는 exec 형태로 쉘을 실행하지않고 명령어를 사용하는형태임.
정리해보면 다음과 같다.
쉘을 실행하지않고 그 자체 함수로 실행한다는... 그런 뜻이라고 하긴함
다만 결국 쉘폼이나 exec폼이나 차이는 크게 없다.
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은 그냥 키값쌍의 설명역할
MAINTAINER는 이제 더이상 사용하지 않음
EXPOSE 는 열어놓을 포트 기본값은 TCP임 당연히 4계층
ENV 는 환경변수
ADD와 COPY는 동일하게 사용가능하다.
다만 차이는 ADD는 주소를 지정할 수 있다.
단, COPY는 안된다 COPY는 파일간에만 가능
방향은 항상 호스트에서 컨테이너로만
ENTRYPOINT 어플리케이션을 실행하기 위한 구성임
가운데는 쉘방식을 쓰는거라 제외
맨 아래도 쉘방식이라 제외
순서는 엔트리포인트 먼저 그다음 CMD
그림을 잘 이해해보면 됨
결국 엔트리포인트만, CMD만, 아니면 둘 다 있는 경우 이렇게만 생각하면 되는 쉬운 내용임.
간단하게 표로 정리하면..
예시는 다음과같음
만약 교체하고싶으면
entrypoint는 명령어 cmd는 옵션 또는 argument
VOLUME 은 볼륨을 생성하거나 마운트할 때 사용
USER 는 entrypoint 와 cmd를 사용할 계정을 지정할 수 있다.
만약에 지정하지 않으면 기본은 root임
컨테이너는 모든 내용을 root로만 작업하고 있는것은 보안에 문제가 될 소지가 있다
WORKDIR 은 명령어를 실행할 때 상대경로로 실행하게되면 WORDDIR이 중요하게 되고 COPY할 때에도 경로를 상대경로로 쓴다면 작업 디렉토리를 의미하는 WORKDIR이 중요해진다.
이거는 편의상 하는거고 가능하면 절대경로를 사용하는 것을 권장한다.
ARG는 도커 파일 내부에서 사용할 변수이다.
변수명 - 기본값형식임
이렇게 사용가능한데 그렇게 많이 사용하지는 않다.
ONBUILD 뒤에 INSTRUCTION을 쓰는데 [RUN CMD ARG] 이런게 들어가고 빌드를 할 때 마다 실행할 명령어를 의미한다. 거의 잘 사용되어지지는 않다.
STOPSIGNAL 이거는 SIGTERM이 생략되어있는거고 어떤 특정 시그널을 받으면 중지시켜라 그런 기능인데 잘 사용되지않음
HEALTHCHECK 는
이런 curl을 해보고 안되면 재시작하게끔 하는 기능도있긴한데 잘 쓰지는 않다 도커에서만 쓰고 쿠버네티스에서는 잘 사용하지는 않음
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 이미지로 작업을 해보자
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
를 만날 때마다 다시 커밋하는 과정을 반복하게됨
/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/
이미지를 가지고 작업할 내용을 공부할 예정 미리 한 번 보면 좋음