Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
Tags
- 2206
- COLAB
- elasticsearch
- image
- github
- java
- GIT
- logstash
- python3 #동적계획법 #permutations
- 정보처리기사실기
- filebeat
- 벽부수고이동하기
- kibana
- 안드로이드스튜디오
- HAXM
- KT
- 개발자로드맵
- javascript #콜백함수 #비동기
- YOLO
- container
- tensorflow2
- KT인턴
- 계정 여러 개 동시 사용
- 백준
- 호스팅
- docker
Archives
- Today
- Total
코딩하고자용 블로그
Docker docs 정리 (2) - Get Started 본문
본 글은 Docker docs 내용을 한글로 작성해가면서 이해하고자 하였으며, 이에 대한 결과물입니다.
글 내용 중 필자의 생각을 첨가하여 docs와 완전히 일치하지 않음을 알려드립니다.
따라서 정확한 이해를 위해 아래의 docs를 정독하시고, 참고용으로만 사용하시길 바랍니다.
https://docs.docker.com/
Docker Documentation
docs.docker.com
Start the tutorial
docker run -d -p 80:80 docker/getting-started
# -d : detached mode(in the background)
# -p 80:80 : 호스트의 port 80번과 컨테이너의 port 80qjsdmf aovld
# docker/getting-started : 사용할 이미지 예시
# -dp 라고 한번에 적어도 됨.
- Docker Desktop을 통해, 컨테이너의 shell에 접근하여 라이프사이클의 변동을 줄 수 있다.
What is a container?
- host machine의 다른 모든 프로세스와 격리된 machine의 샌드박스? 프로세스.
- image의 instance. DockerAPI or CLI를 통해 create, start, stop, move, delete 등 조작 가능
- 모든 os에서 실행 가능
Sample application
- 간단한 TO-DO List를 통해 사용법을 익혀보자
- 앱 빌드를 위해, DockerFile을 사용해야 한다.
- DockerFile은 컨테이너 이미지를 만들기 위해 사용되는 스크립트이다.
- 다운받은 프로젝트의 container image를 빌드해보자.
docker build -t getting-started .
- 위 명령어로 도커파일을 통해 새 컨테이너 이미지를 생성한다.
- -t : 이미지에 태그 지정. 최종 이미지의 name이라 생각하자.
- 위 명령으로 이미지가 생성되었으므로, app을 실행해보자.(컨테이너 생성)
docker run -dp 3000:3000 getting-started
- 포트 매핑없이는, app 접근이 불가함을 명심하자.
- 몇 초 후, http://localhost:3000 을 열면, 앱이 열리고, item을 추가/삭제가 잘 될 것이다.
Update the application
- app의 update가 일어날 때, 이에 따라 컨테이너도 update 될 필요가 있을 것이다.
- 이미지를 재빌드하더라도, 컨테이너가 업데이트된 것이 아니기에, 현재 실행 중인 컨테이너의 제거가 필요하다.
docker ps
# docker ps를 통해 container-id를 알아낸다.
docker stop <the-container-id>
docker rm <the-container-id>
# 두가지 일을 동시에 할 수도 있다.
docker rm -f <the-container-id>
# 삭제 후, 다시 컨테이너를 생성하면 된다.
docker run -dp 3000:3000 getting-started
Share the application
- 이미지를 docker registry를 통해 공유해보자.
docker login -u YOUR-USER-NAME
docker tag getting-started YOUR-USER-NAME/getting-started
# docker tag를 통해 image에게 새로운 name을 부여
docker push YOUR-USER-NAME/getting-started
Persist the DB
- 컨테이너가 실행될 때 파일 시스템에 대한 이미지의 다양한 계층을 사용한다
- 각 컨테이너에는 파일 생성/업데이트/제거를 위한 자체 scratch space도 있다. 따라서 동일한 이미지를 사용한들 변경 사항은 다른 컨테이너에서 볼 수 없다
# 참고: container에서 terminal로 바로 명령을 실행하기 위해, 아래와 같이 사용할 수도 있다.
# docker ps를 통해 container-id를 알아내도록 하자
docker exec <container-id> cat /data.txt
- 이에 도커에서는 Volume을 사용한다.
- Volume : 컨테이너의 특정 파일 시스템 경로를 호스트 시스템에 다시 연결하는 기능을 제공
- 해당 디렉토리의 변경 사항을 호스트 시스템에서도 볼 수 있게 되는 것
- named volumes
- /etc/todos/todo.db에 있는 SQLite 데이터베이스에 데이터를 저장한다고 하자.
- 이 파일을 다른 host에서도 접근이 가능하다면, persist할 수 있을 것이다.
- name volume을 단순히 데이터 버킷(bucket of data)로 생각해보자
- 도커는 이 물리적인 공간을 유지해줄 것이고, 우리는 volume의 이름만 기억하면 된다
docker volume create todo-db
# volume mount를 명명해주면서 container를 생성해보자.
docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
# data가 쌓이는 곳에 대한 정보를 알기 원한다면
docker volume inspect todo-db
# 결과
[
{
"CreatedAt": "2022-08-23T07:04:43Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/todo-db/_data", # 데이터가 저장되는 디스크의 실제 위치
"Name": "todo-db",
"Options": {},
"Scope": "local"
}
]
- bind mounts
- named volumes과 달리 호스트에서 정확한 Mountpoint를 제어할 수 있다.
Named Volumes | Bind Mounts | |
Host Location | Docker chooses | You control |
Mount Example(using -v) | my-volume:/usr/local/data | /path/to/data:/usr/local/data |
Populates new volume with container contents | Yes | No |
Support Volume Drivers | Yes | No |
- 개발 workflow를 지원하기 위한 컨테이너를 실행해보자.
# m1 mac 기준
docker run -dp 3000:3000 \
-w /app -v "$(pwd):/app" \
node:12-alpine \
sh -c "apk add --no-cache python2 g++ make && yarn install && yarn run dev"
# -w /app : working directory 설정
# node:12-alpine : 사용할 이미지
# 컨테이너 생성 후 log 확인
docker logs -f <container-id>
- 이후에 변경사항이 있다면 변경 후 컨테이너를 중지하고 새 이미지를 빌드하면 refresh를 통해 간단히 로컬 개발 가능!
- 이처럼 Bind Mount를 사용하는 것은 로컬 개발 설정에서 매울 일반적이다.
- 장점 : 개발 머신에 모든 빌드 도구와 환경을 설치할 필요가 없음!
- Docker Compose를 통해 명령을 단순화할 수 있음(추후 설명)
Multi container app
- 지금까지는 단일 컨테이너 앱으로 작업해왔지만 이번엔 MySQL 자체를 추가해보고자 한다.
- 음? MySQL은 그럼 어디서 실행되는거에요? 컨테이너에 설치해서 사용해야되나요?
- 답변은 No. 각 컨테이너는 한 가지 작업을 수행하고 잘 수행하게 설계해야된다.
- API와 Frontend를 DB와 다르게 확장해야 할 가능성이 큼
- 별도의 컨테이너를 사용하여 버전을 격리하고 업데이트할 수 있음
- 다중 프로세스 실행은 process manager를 필요로 해서
- Container networking
- 컨테이너는 기본적으로 격리되어 실행되며 동일한 시스템의 다른 프로세스나 컨테이너에 대해 알지 못함.
- 각각의 컨테이너들이 통신하도록 -> Networking!
- 네트워크에 컨테이너를 두는 방법은 두 가지이다.(두 컨테이너가 같은 네트워크에 없다면 통신할 수 없다)
- 시작할 때 할당
- 기존 컨테이너를 연결
docker network create todo-app
docker run -d \
--network todo-app --network-alias mysql \
--platform "linux/amd64" \
-v todo-mysql-data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=secret \
-e MYSQL_DATABASE=todos \
mysql:5.7
# docker가 volume을 자동 생성해줌
docker exec -it <mysql-container-id> mysql -u root -p
mysql> SHOW DATABASES;
- connect to MySQL
- MySQL 컨테이너를 생성하였다면, 이제 사용해보자.
- 앱을 MySQL이라는 호스트에 연결하기만 하면 됨.
docker run -it --network todo-app nicolaka/netshoot
dig mysql # dig? 유용한 DNS tool
#answer section을 통해 IP를 알 수 있다
- TODO 앱은 MySQL 연결 설정을 지정하기 위해 몇 가지 환경 변수 설정을 지원한다.
- MYSQL_HOST
- MYSQL_USER
- MYSQL_PASSWORD
- MYSQL_DB
- 이러한 환경 설정을 통해 나의 MySQL 환경에 접근할 수 있다.
docker run -dp 3000:3000 \
-w /app -v "$(pwd):/app" \
--network todo-app \
-e MYSQL_HOST=mysql \
-e MYSQL_USER=root \
-e MYSQL_PASSWORD=secret \
-e MYSQL_DB=todos \
node:12-alpine \
sh -c "yarn install && yarn run dev"
Use Docker Compose
- Docker Compose : 다중 컨테이너 애플리케이션(multi-container application)을 정의하고 공유하는 것을 돕는 tool
- compose로 파일에 application stack을 정의할 수 있고, project repo의 루트에 보관할 수 있으며, 다른 사람이 쉽게 프로젝트에 기여할 수 있다.
- docker desktop 설치 시, 함께 Docker Compose가 설치된다.
docker-compose version
- 이제, compose file을 생성해보자.
- app project의 root에 docker-compose.yml을 생성하자.
version: "3.7" # schema vesion 설정
services: # 우리의 앱에서 실행되기를 원하는 컨테이너(서비스) 리스트
app:
image: node:12-alpine
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000 #service에 대한 port 정의
working_dir: /app # 작업 디렉토리
volumes: # volume mapping
- ./:/app
environment:
MYSQL_HOST: mysql
MYSQL_USER: root
MYSQL_PASSWORD: secret
MYSQL_DB: todos
- MySQL 서비스 정의
version: "3.7"
services:
app:
# The app service definition
mysql:
image: mysql:5.7
volumes:
- todo-mysql-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: todos
volumes:
todo-mysql-data:
- 이처럼 docker-compose.yml 작성을 완료하였다면, 이를 실행시켜보자.
- app/db copy본이 실행되고 있어선 안됨을 명심하자.
- 아래의 명령으로 application stack을 실행한다.
docker-compose up -d # -d : background 실행
#output
Creating network "app_default" with the default driver
Creating volume "app_todo-mysql-data" with default driver
Creating app_app_1 ... done
Creating app_mysql_1 ... done
Image-building best practices
- 이미지를 생성했을 때 docker scan 명령을 사용하여 보안 취약점을 스캔하는 것이 좋다.
- 또한, docker image history 명령을 사용해 이미지 내에서 각 레이어를 생성하는데 사용된 명령을 볼 수 있음.
- 컨테이너의 이미지 빌드 시간을 줄이려면 어떻게 해야 좋을까?
- 우리가 이미지를 변경할 때, yarn dependencies를 다시 설치해야하는 번거로움이 있다.
- 이를 해결하기 위해 종속성 캐싱을 지원하도록 Dockerfile을 재구성해야한다.
- .dockerignore 파일은 이미지 관련 파일만 선택적으로 복사하는 쉬운 방법임.
- 이를 활용하면, 빌드가 훨씬 빨라질 것이다!
- 특히, 다단계 빌드(multi-stage build)에서 이미지를 생성할 때 훨씬 효과적이다.
- Maven/Tomcat 예제
- Java 기반 응용 프로그램을 빌드할 때 소스 코드를 Java 바이트 코드로 컴파일하려면 JDK가 필요함.
- 그러나 해당 JDK는 프로덕션엔 필요하지 않음.
- 또한 Maven이나 Gradle과 같은 도구를 사용하여 앱을 빌드할 수도 있다.
# syntax=docker/dockerfile:1
FROM maven AS build
WORKDIR /app
COPY . .
RUN mvn package
FROM tomcat
COPY --from=build /app/target/file.war /usr/local/tomcat/webapps
- React 예제
# syntax=docker/dockerfile:1
FROM node:12 AS build
WORKDIR /app
COPY package* yarn.lock ./
RUN yarn install
COPY public ./public
COPY src ./src
RUN yarn run build
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
'Computer Science > Server' 카테고리의 다른 글
ngx_http_proxy_connect_module을 활용한 CONNECT 요청을 처리하는 Docker 기반 nginx 서버 생성 (0) | 2024.06.21 |
---|---|
ElasticStack에 대한 정리 (0) | 2023.04.22 |
Docker docs 정리 (1) - Overview (0) | 2022.08.22 |