일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- Today
- Total
- 라즈베리파이
- 빈 중복 오류
- Spring interceptor
- Spring
- qualifier
- 스프링 Configuration
- UsernamePasswordAuthenticationFilter
- RequiredArgsConstructor
- DI컨테이너
- Autowired 옵션
- 롬복 Qualifier
- docker
- autowired
- ComponentScan
- 스프링 빈 조회
- HandlerMethodArgumentResolver
- 라즈베리파이4
- DI
- 객체지향
- 스프링 컨테이너
- Servlet Filter
- 스프링 싱글톤
- 스프링 빈
- 의존관계 주입
- 스프링
- 싱글톤 컨테이너
- 생성자 주입
- springsecurity
- beandefinition
- 도커
그날그날 공부기록
Docker 기본 명령어 맛보기 본문
쿠버네티스를 공부하기 전 도커를 간단하게 다루어 보았다.
로컬 환경이 아닌 GCP의 CE로 가상 머신을 만들어 진행하였다. 그래서 배포 역시 docker hub를 사용하지 않고 gcr을 사용한다.
도커는 애플리케이션을 개발, 배송, 및 실행하기 위한 개방형 플랫폼이다.
도커의 컨테이너화 기능을 통해 어디서든 도커만 설치되어 있다면 이미지를 업로드/다운로드하여서 실행할 수 있다.
이미지를 만들고, run명령어를 통해 이미지를 컨테이너화 하여 실행한다.
docker run hello-world
hello-world는 “Hello from Docker!”라는 문장을 반환하는 간단한 컨테이너이다.
명령어를 실행시키면 docker daemon은 해당 이미지를 로컬에서 검색하고, 없다면 Docker Hub라는 공용 저장소에서 이미지를 저장하고, 실행시킨다.
→ docker images 명령어를 통해 저장된 이미지들을 볼 수 있다.
docker ps
ps 명령어로 현재 실행중인 컨테이너를 확인할 수 있다.
실행이 종료된 컨테이너까지 확인하고 싶다면 -a 옵션을 추가하면 확인할 수 있다.
해당 명령어를 실행하면 도커에서 생성한 UUID와 실행에 대한 정보들이 표시된다.
컨테이너의 이름은 무작위로 생성되지만 다음 명령어로 이름을 지정할 수 있다.
docker run --name ${container-name} hello-world
빌드
이미 생성된 도커 이미지를 사용할 수도 있지만 직접 이미지를 생성할 수 있다.
다음과 같이 Dockerfile이라는 파일을 생성하였다.
# 노드를 사용한 예제이다. 부모 이미지로 노드의 lts버전을 사용한다.
FROM node:lts
# 컨테이너의 작업 디렉토리를 /app으로 설정한다.
WORKDIR /app
# 현재 디렉토리의 내용을 디렉토리의 /app으로 복사한다. . -> /app
ADD . /app
# 컨테이너의 80번 포트를 외부와 연결할 수 있도록 개방한다.
EXPOSE 80
# 컨테이너가 실행될 때 노드를 사용하여 app.js를 실행한다.
CMD ["node", "app.js"]
다음과 같은 app.js라는 node 애플리케이션도 생성한다.
const http = require('http');
const hostname = '0.0.0.0';
const port = 80;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\\n');
});
server.listen(port, hostname, () => {
console.log('Server running at http://%s:%s/', hostname, port);
});
process.on('SIGINT', function() {
console.log('Caught interrupt signal and will exit');
process.exit();
});
두 파일을 모두 생성했다면 빌드 명령어를 입력한다.
docker build -t ${이미지명:이미지태그} ${빌드 콘텍스트}
docker build -t node-app:0.1 .
빌드 콘텍스트는 주로 현재 디렉터리(’ . ‘)를 사용하지만 필요시 다른 디렉터리를 지정할 수 있다.
-t 옵션으로 도커 이미지 이름을 지정할 수 있다.
-f ${Dockerfile 위치} 옵션을 사용해 다른 위치의 Dockerfile 사용이 가능하다.
실행
다음 명령어를 사용하여 빌드한 이미지를 실행한다.
docker run -p 4000:80 --name my-app node-app:0.1
—name 옵션은 컨테이너의 이름을 지정하는 데 사용된다.
-p는 호스트의 4000번 포트를 컨테이너의 포트 80번과 매핑한다.
이후 http://localhost:4000에 접속을 해보면 Hello World가 출력되는 것을 확인할 수 있다.
-d 옵션을 추가하면 컨테이너를 백그라운드에서 실행할 수 있다.
실행 전에 해당 컨테이너를 멈추고 삭제해야 한다.(같은 포트, 같은 이름 사용할 예정)
docker stop my-app && docker rm my-app
각각 적어주어도 무방
모든 컨테이너를 정지, 종료하려면 다음과 같이 입력한다.
docker stop $(docker ps -q)
docker rm $(docker ps -aq)
컨테이너가 삭제된 후 -d옵션을 주어 다시 실행한다.
docker run -p 4000:80 --name my-app -d node-app:0.1
백그라운드에서 실행하였기 때문에 서버의 로그가 보이지 않는다.
로그를 보기 위해서는 docker ps 명령어로 컨테이너의 id를 알아낸 후 다음 명령어를 입력한다.
docker logs ${CONTAINER ID}
💡 여기서 컨테이너 id는 꼭 전부 다 입력할 필요는 없다. 일부분만 입력해도 일치하는 부분의 컨테이너가 유일하다면 알아서 인식한다!
노드 애플리케이션의 일부분을 다음과 같이 수정 후 실행해 보았다.
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Welcome to Docker\\n');
});
app.js를 변경 후 태그를 0.2로 변경하여 새로운 이미지를 생성한다.
docker build -t node-app:0.2 .
빌드시 나오는 로그를 보면 WORKDIR 까지는 기존 캐시 계층을 사용하는 것을 알 수 있다.
app.js를 변경하였기 때문에 ADD부터 변경이 진행된다.
새로운 이미지 역시 백그라운드로 실행한다.
docker run -p 8080:80 --name my-app2 -d node-app:0.2
호스트의 4000 포트는 이미 사용 중이므로 8080을 사용한다.
컨테이너의 80번 포트는 동일한데, 이는 두 개의 컨테이너가 서로 다른 컨테이너이기 때문에 겹치치 않는다.
디버그
실시간으로 컨테이너의 로그를 확인하려면 -f를 추가한다.
docker logs -f ${CONTAINER ID}
실행 중인 컨테이너의 셸을 실행하고 싶다면 docker exec를 사용한다.
-it는 pseudo-tty를 할당하고, 입력을 열린 상태로 유지하여 컨테이너와 상호작용 할 수 있도록 해준다.
docker exec -it ${CONTAINER ID} bash
<aside> 💡 TTY(teletypewriter) 리눅스 디바이스 드라이브 중에서 콘솔이나 터미널을 의미 pseudo terminal은 진짜 터미널이 아닌 유사(가짜) 터미널이다.
</aside>
셸 명령어를 사용할 수 있고 exit으로 종료할 수 있다.
컨테이너의 메타데이터를 확인하려면 docker inspect를 사용한다.
docker inspect ${CONTAINER ID}
컨테이너 id, 생성일 등 관련 정보가 json으로 주르륵 나온다.
-format을 사용하면 json에서 특정한 필드를 가져올 수 있다.
#ip를 가져온다.
docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' [container_id]
배포(GCR이용)
위에서 빌드한 이미지를 gcr에 푸시하고, 새로운 환경에서 이미지를 받아 실행할 수 있다.
gcr에서 호스팅 하는 비공개 저장소에 이미지를 푸시하려면 이미지 이름을 다음과 같이 설정해야 한다.
${HOST NAME}/${PROJECT ID}/${IMAGE}:${TAG}
💡 HOST NAME: gcr.io PROJECT ID: 현재 프로젝트 id IMAGE: 배포하려는 이미지 이름 TAG: 아무 문자열이나 가능. 없다면 default로 latest가 붙는다.
우선 프로젝트 id를 알기 위해 다음 명령어를 입력한다.
gcloud config list project
생성했던 node-app:0.2의 이미지/태그명을 변경한다.
docker tag node-app:0.2 gcr.io/${PROJECT ID}/node-app:0.2
docker image 명령어로 확인하여 이미지/태그명이 잘 변경되었다면 gcr에 이미지를 푸시한다.
docker push gcr.io/${PROJECT ID}/node-app:0.2
웹에서 이미지가 잘 올라갔는지 확인한다.
Container Registry로 들어가 확인하거나 http://gcr.io/${PROJECT ID}/node-app로 방문할 수 있다.
새 가상 머신을 실행하거나 현재 가상 머신의 모든 컨테이너/이미지를 삭제한다.
docker stop $(docker ps -q)
docker rm $(docker ps -aq)
node:lts이미지를 삭제하기 위해서는 자식 이미지를 먼저 삭제해야 한다.
docker rmi node-app:0.2 gcr.io/[project-id]/node-app node-app:0.1
docker rmi node:lts
docker rmi $(docker images -aq) # 남아있는 모든 이미지를 지운다.
docker images
이미지를 다운받고, 실행한다.
docker pull gcr.io/${PROJECT ID}/node-app:0.2
docker run -p 4000:80 -d gcr.io/${PROJECT ID}/node-app:0.2