2024.03.07(목)
CI/CD(CI CD, 지속적 통합/지속적 배포): 개념, 툴, 구축, 차이
컴퓨팅 자원(resource)의 추상화를 일컫는 광범위한 용어로 컴퓨터 안에 또 다른 가상의 컴퓨터가 존재하도록 하는 기술
호스트: 다른 시스템을 가상화하여 실행하는 컴퓨터
게스트: 호스트 시스템 위에 가상화되어 제공되는 (가상) 시스템
널리 이용되고 있는 컨테이너 기반 가상화 플랫폼
도커 이미지(Docker Images)
실행 가능한 컨테이너를 만들기 위한 거푸집
도커 컨테이너(Docker Containers)
도커가 실행하는 격리된 환경과 그 내부
docker search <name>
명령어로 탐색 가능docker run <name>
으로 실행 (local에 존재하지 않는 경우 pull & run)172.17.0.2
에서 실행 중이라는데 접속이 안됨❓ WHY?
- Windows와 Mac에서 실습할 때 Docker Desktop을 사용하게 되는데 이 경우 VM 위에서 Docker Engine을 실행하게 됨
- 기본적으로 Docker Container는 자체적인 네트워크 환경을 가지고 있고, 이는 Host의 네트워크와 격리되어 있음
- 따라서 Host에서 Container의 서비스에 접근하려면 Host와 Container 간의 통신을 중계해주는 포트 포워딩(Port Forwarding)을 사용하여 Host의 특정 포트로 들어온 요청을 Container 내부의 포트로 전달하여 서비스에 접근해야함!
- Linux에 Docker Engine을 직접 설치하는 실제 배포 환경에서는 VM과 같은 별도의 중간 계층 없이 Docker가 Host의 네트워크 인터페이스에 직접 연결되기 때문에 Container는 Host와 동일한 네트워크에 존재하게 되어 바로 접속 가능
docker run
명령어에 -p
, --publish
option을 사용해서 포트 포워딩을 해주어야 함!-p <host-port>:<container-port>
형식⚠️ 주의할 점
- 공식 문서에서도 강조되어 있듯 Container의 port를 publishing할 때 Host의 IP address를 명시하지 않고 port만 사용하면 (i.e.,
-p 127.0.0.1:80:80
대신-p 80:80
) Docker는 default로 post를 모든 interface에 publish (address0.0.0.0
) ⇒ Docker Host 뿐만 아니라 외부에 공개됨 (누구나 접근 가능)- localhost IP address (
127.0.0.1
)를 포함하면 Docker Host만 해당 Container의 port에 접근 가능
docker start <container-name/id>
docker stop <container-name/id>
docker ps
docker ps -a
docker rm <container-name/id>
docker images
docker rmi <image-name/id>
(해당 이미지로 만든 컨테이너가 없어야 삭제 가능)docker run -p 8080:80 **-it** httpd /bin/bash
container 내부 터미널이 열리고 다음과 같이 serve되고 있는 html 문서를 찾아 수정
grep DocumentRoot /usr/local/apache2/conf/httpd.conf
cd htdocs
cat index.html
(파일 내용 출력)cat > index.html
(파일 내용 덮어쓰기) 또는 cat >> index.html
(기존 파일 내용 추가) → Ctrl + D
키를 눌러서 저장<html><body><h1>Hello World!</h1></body></html>
httpd-foreground
(웹서버 실행)exit
(컨테이너 터미널 나오기 & 실행 중단)
docker start <container-name/id>
로 다시 실행 & docker exec -it <container-name/id> /bin/bash
로 컨테이너 터미널 접속 가능
docker commit <container-name/id> [repository-name[:tag]]
으로 컨테이너를 이미지로 만들기!
8080:80
을 사용했으니 이번에는 8081:80
으로 포트 포워딩80
이므로 컨테이너 포트는 80
그대로, 호스트 포트만 바꿔줌계층 구조를 이용하여 도커 이미지를 만드는 절차를 기술하는 파일 (텍스트)
FROM [--platform=<platform>]<image>[AS <name>]
RUN <command>
ENTRYPOINT ["executable", "param1", "param2"]
FROM httpd:latest
RUN echo "<html><body><h1>Docker Build Test</h1></body></html>" > /usr/local/apache2/htdocs/index.html
ENTRYPOINT /usr/local/bin/httpd-foreground
이미지 빌드 명령어: docker build [options] PATH | URL | -
→ local에 이미지가 저장됨
docker build -t my_httpd:0.2 .
이미지 레지스트리에 올리기
docker login
docker tag <source-image> <target-image>
latest
태그가 할당됨<docker_hub-id>/<image-name>
형식의 이름 사용docker push <image-name>
만들어둔 컨테이너 및 이미지 모두 지우고 이미지 레지스트리에 올려둔 이미지를 다운받아 컨테이너 실행해보기
문제
hello:0.1
베이스 이미지: ubuntu:22.04
패키지 설치: python3 (apt-get 이용)
응용 스크립트 설치: hello.py
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y python3
COPY hello.py .
ENTRYPOINT ["python3", "hello.py"]
> docker run hello:0.1
Hello World from Python!
실습
COPY
hello.py .
라는 명령으로 현재 로컬 디렉토리에 있는 hello.py
파일을 Docker 이미지로 복사 & ENTRYPOINT
명령으로 실행
따라서 Dockerfile
과 같은 위치에 hello.py
파일을 작성해줌!
환경 변수 사용해보기: ENV
명령어로 환경 변수를 지정
-e
, --env
option으로 환경 변수 설정 가능
--rm
option으로 실행이 끝나면 컨테이너를 자동으로 삭제(clean up)
-d
, --detach
option으로 컨테이너를 background에서 실행
docker run -d --rm tomcat
docker logs <container-name/id>
로 로그 확인 가능docker inspect <container-name/id>
로 도커 객체 정보 확인 가능지금은 컨테이너의 이름을 지정해주지 않아서 Docker가 이름을 무작위로 정하게 되는데 --name
option으로 컨테이너 이름을 지정할 수 있음
docker run --rm -d -P --name my_tomcat tomcat
-P
option 사용 시 컨테이너의 포트를 호스트의 임의의 포트에 매핑 → docker ps
에서 포트 번호 확인 가능my_tomcat
으로 지정됨docker cp
명령어 사용ADD
지시자 활용docker run
에서 -v
, --volume
option으로 호스트의 특정 디렉토리를 컨테이너와 공유docker run
에서 -v
, --volume
option으로 호스트와 공유하는 것은 비슷하지만 마운트하는 것은 추상화된 볼륨/var/lib/docker/volumes/<volume-name>/_data
에 저장됨➕ 바인드 마운트와 도커 볼륨 모두 컨테이너가 종료되더라도 data를 보존하기 위해 사용
도커 볼륨을 사용하는 것을 더 추천하는 듯
Docker volumes vs. bind mounts - LogRocket Blog
실습 준비
docker run --rm -d -p 8080:80 --name my_nginx nginx:latest
대체할 파일 하나 준비
docker exec -it my_nginx /bin/bash
로 컨테이너 접속
/usr/share/nginx/html
폴더에 50x.html
과 index.html
이 존재하고 index.html
이 serve되고 있음
준비할 html 파일 이름을 index.html
로 해서 덮어쓰기
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html {
color-scheme: light dark;
}
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Hello</h1>
<p>A file from Host!</p>
</body>
</html>
docker cp index.html my_nginx:/usr/share/nginx/html
로 호스트에 있는 파일을 컨테이너로 복사 (호스트 → 컨테이너)
docker cp my_nginx:/usr/share/nginx/html/50x.html .
로 컨테이너의 파일을 호스트로 복사 (컨테이너 → 호스트)
ADD
지시자를 이용해 호스트가 제공하는 파일을 특정 위치에 둠FROM nginx:latest
ADD ./index.html /usr/share/nginx/html/new.html
CMD ["nginx", "-g", "daemon off;"]
docker build -t your_nginx .
로 Dockerfile 기반으로 이미지를 빌드해 로컬에 저장docker run --rm -d -p 8888:80 --name your_nginx your_nginx
docker run -v <host-path>:<container-path> <image>
docker run -it -v .:/host_directory ubuntu:22.04 /bin/bash
docer volume
create <volume-name>
docker run --rm -d -p 8888:80 -v my-volume:/usr/share/nginx/html --name my_nginx nginx:latest