-
도커 (8)컨테이너이름, rm, v, 요약, 리소스정리, cp, CMD & ENTRYPOINTdocker 2022. 2. 26. 17:48
============
container run할 때 이름 안주기
C:\docker> docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2fdfc16ec42c example/echo:latest "/bin/bash" 23 seconds ago Up 22 seconds 0.0.0.0:58496->8080/tcp zealous_mcnulty ⇐ 해당 컨테이너가 detach 모드로 전환
9317682730d9 example/echo:latest "go run /echo/main.go" 5 minutes ago Up 5 minutes 0.0.0.0:58470->8080/tcp tender_merkle
docker container run --name 옵션을 생략하면 임의의 이름을 생성해서 제공
웹서버가 하나밖에 없으면 쉽게 제어하려면 이름을 가져가는게 좋다. ID치려면 어려우니까
근데 100개 띄우면 이름을 부여하는게 부담스러워진다
->운영환경에선 이름 사용 안해, 자동 부여되도록 해
개발할 때나 컨테이너 한 두개 띄울 때 액세스 쉽게 하려고 이름 부여함
포트랑 마찬가지네
============
--rm
컨테이너를 이름 부여해서 run하는건 좋지 않다
운영할 땐 같은 컨테이너를 여러개 띄울텐데
--name으로 이름 부여하고 같은 run을 두번 입력하면 --name이름 같다고 실행 안됨 유니크해야해
stop해도 같은 이름으로 run안된다
다시 띄우려면 rm해야해
- 개발하는 단계에서 ID를 이용해서 access하려고 하면 헷갈림
- 이름을 사용하려고 하면 중복되면 안되고
개발 시 컨테이너가 종료되면 자동으로 삭제되게 설정할 수 있다, --rm옵션으로
docker container run --name myreact-app --rm -itd -p 3000 myapp
docker container stop myreact-app
이제 stop하면 지워짐
*저거 -P옵션하면 EXPOSE 3000이라고 돼 있으면 3000번 포트를 노출하고, 임의의 포트를 3000과 연결함
EXPOSE 3000 + -P = -p 3000
---
-v
개발단계에서의 얘기
PS C:\docker> docker container run --name myreact-app --rm -itd -p 8282:3000 myapp
이 상태에서 리액트 어플리케이션의 내용을 변경하고 싶어
: 내 PC의 소스 코드를 수정 → docker image build → docker container run
이렇게 해야되는데 빌드하는데 시간이 오래 걸리고...
내가 갖고 있는 파일을 실행 컨테이너와 공유할 수 있으면 어떨까?
도커는 내가 준 파일을 특정디렉토리에 따놓고 그걸 run만 하고 있는데,
배포말고 개발단계에서는 그 시간을 좀 줄이면 어떨까
호스트의 특정 디렉토리를 컨테이너의 내부와 공유! 복사하고 빌드안해도 되게! 볼륨매핑!
VOLUME을 이용해서 호스트의 특정 디렉터리를 컨테이너 내부와 공유해서 복사하고 빌드하는 시간을 단축
http://pyrasis.com/book/DockerForTheReallyImpatient/Chapter07/11
컨테이너를 run하는데 -v옵션을 줘서
-v 호스트디렉토리 : 컨테이너내부디렉토리
호스트 디렉토리를 컨테이너 내부 디렉토리와 연결
내용을 바꾸면 변경자체가 공유돼있기 때문에 바뀐다, 컨테이너 run 중에도 바꿔도 요청 다시하면 바뀐다
볼륨 : 호스트와 컨테이너가 공유디렉토리를 쓴다
활용(1)
호스트의 변경을 여러 컨테이너에 함께 반영하고 싶을 때
웹서버를 여러개 띄웠는데, 소스코드가 전부 다르면 안되니까
하나의 공유디렉토리를 걸어놓고 모든 컨테이너들이 소스코드를 받아가게
활용(2)
컨테이너가 휘발성 객체, 죽을수도 사라질수도
일반적인 서비스용 컨테이너 스프링부트와같은, REST API를 제공하는 얘들은 돌다가 사라져도 또 띄우면 똑같은 동작을 할 수 있다 = stateless, 상태관리하지않고 동작하다 사라지면 또 띄우면 똑같이 동작
그에 비해서 mysql서버는 계속 달라, 데이터가 쌓여, stateful한 서비스
이건 컨테이너가 죽어버리면 거기있던 데이터가 날아가버리면 안된다
stateful한 서비스들은 데이터 유지관리보관해야하는 기능이 필요하다, persistence하게 관리해야한다
이때 볼륨매핑을 씀
mysql이죽어서 다른 mysql이 올라오더라도 같은 상태로. 데이터를 컨테이너내부가 아니라 볼륨매핑을 통해 호스트측에다가
여러개의 컨테이너에게 동일한 최신데이터를 줘야할 때!
============
요약
제일 중요한건 -itd 옵션
입력과 출력을 공유하고
detach모드로 동작시키고
도커파일을 만들어서 내가만든 리액트, 자바를 이미지화
실행중인 컨테이너에 attach할 때
attach -> 빠져나오면 컨테이너가 죽어 그래서 detach키를 통해서 detach모드로 빠져나와야
exec해서 쉘을 실행 -> 해당 컨테이너에 쉘이 제공돼야하는 경우 그렇게 빠져나오면 컨테이너의 메인프로세스는 동작하므로 컨테이너가 중지안됨
--rm 하면 개발환경에서 유용
포트바인딩은 -p
컨테이너 port는 고정돼도 상관없다 컨테이너마다 전부 8080이어도 괜찮
호스트port는 걔마다 달라야해, 운영단계에선 일일이 지정해주는것보단 지정하지 않고 자유롭게 배정될 수 있도록 하는게 방법
이미지만들때 사용자 입력 안들어가게 : -y말하는거겠지
파일사이즈줄이기 : &&말하는거겠지
============
0)
컨테이너도 하나의 컴퓨터니까 포트도 여러개고
거기에 서버프로그램 여러개 두면, 각각 포트가 필요할텐데(컨테이너 안에 db, 스프링부트, 리액트 각각 설정에 포트를 써놨을 텐데)
EXPOSE를 보다가, 왜 Dockerfile에서 왜 딱히 저 여러개랑 각각 다른 호스트 포트랑 연결하는 설정이 없는것 같냐
이미지 만들때도 -p옵션에서 하나만 연결하고
->컨테이너에 서버를 여러개 둘 수 있다o, 얘네 각각 바깥 포트 몇번이랑 연결할지 설정할 수 있다o
= 컨테이너 하나에 DB, 리액트, 스프링부트 둘 수 있고 명령어나 Dockerfile로 각각 다른 호스트 포트와 연결할 수 있다
->근데! 좋은 설계는 컨테이너 당 프로그램 하나 돌리는게 깔끔한거고 원칙이래!이게 바로 시원한 답변이었다
->좋은 설계는 DB, 리액트, 스프링부트를 각각 컨테이너 하나씩에만 둔다 서로 연결을 할 수 있는 방법이 있다(당연), 쉽게하는 건 도커컴포즈지
============
리소스 정리 (모든 컨테이너와 이미지를 삭제)
PS C:\Users\myanj> docker container rm -f $(docker container ls -aq)
PS C:\Users\myanj> docker image rm -f $(docker image ls -aq)
============
cp(▽볼륨매핑하면 될걸 왜..)
nginx (웹 서버) 이미지를 이용해서 컨테이너를 생성
PS C:\Users\myanj> mkdir c:\docker\webroot
PS C:\Users\myanj> docker run -itd --name mywebserver -p 8080:80 nginx
이제 컨테이너 내부의 파일을 수정해보려고해
attach해서 들어가봤더니 리스닝중이야
detach모드 : 컨+p+q로 해서
exec로 다시 해보자
(1)
PS C:\Users\myanj> docker container attach mywebserver
2022/01/26 00:38:40 [notice] 39#39: signal 28 (SIGWINCH) received
2022/01/26 00:38:40 [notice] 38#38: signal 28 (SIGWINCH) received
:
Ctrl + p + q ⇒ detach 모드로 전환
(2)
PS C:\Users\myanj> docker container exec -it mywebserver /bin/bash
root@bca3ef603d99:/#
root@bca3ef603d99:/# cd /usr/share/nginx/html/ ⇐ nginx의 기본 웹 루트 디렉터리
root@bca3ef603d99:/usr/share/nginx/html# ls
50x.html index.html
root@bca3ef603d99:/usr/share/nginx/html# cat index.html ⇐ 브라우저를 통해서 확인한 페이지
<!DOCTYPE html>
<html>
<head>
:
:
근데 vi해보니까 없어서 exit로 빠져나옴(다운받아서 해도 되지만 그냥 나옴)
(3)
컨테이너의 파일을 가져와서, 수정하고, 다시 넣으려고 해
cp :
▽앞에것을 복사, 뒤의 것이 복사할 곳. : 로 컨테이너인지 호스트인지를 구분
docker container cp mywebserver:/usr/share/nginx/html .
앞에 있는걸 . 로 가져와
한칸 띄우기 전까지 SRC, 뒤에것이 목적지
============
수정을 한 뒤 수정한 index.html 파일을 컨테이너 내부로 복사
PS C:\docker\webroot> docker container cp .\html\index.html mywebserver:/usr/share/nginx/html\index.html
확인할땐 웹서버로 요청을 해보든지
cat으로 하든지
PS C:\docker\webroot> docker container exec mywebserver cat /usr/share/nginx/html/index.html
============
commit
이때 ! 변경된 내용을 포함하고 있는 컨테이너를 이미지로 저장,
-a : 저작자
-m : 커밋메시지
컨테이너 이름 다음에 이름을 주기
PS C:\docker\webroot> docker commit -a "만든사람 myanjini" -m "새로운 컨텐츠를 포함한 웹 서버" mywebserver mynewwebserversha256:4ce4c3809f8968157c11fcd46f124d0b51e34ec43cb52a5884d363aa55c51721
PS C:\docker\webroot> docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
mynewwebserver latest 4ce4c3809f89 21 seconds ago 141MB
nginx latest 605c77e624dd 3 weeks ago 141MB
============
생성한거 도커허브에 등록하기
1.태그바꾸기
docker image tag
내 계정명이 포함돼있는 새로운 이름으로 해야해
docker image tag mynewwebserver:latest myanjini/mynewwebserver:1.0
(처음에 commit할 때 이름줘도 된다)
2.
docker push 이미지명
PS C:\docker\webroot> docker push myanjini/mynewwebserver:1.0
============
도커 허브에 등록된 이미지를 이용(▽원래있는걸로하잖아)해서 새로운 컨텐츠를 포함한 컨테이너를 실행
docker container run --name mynewwebserver -d -p 9090:80 이미지이름
PS C:\docker\webroot> docker container run --name mynewwebserver -d -p 9090:80 myanjini/mynewwebserver:1.0
============
CMD vs ENTRYPOINT
도커파일에서 두개 다 컨테이너가 실행됐을 때 명령어를 실행해주는 기능
이재홍 아저씨 문서에 다 있다
http://www.pyrasis.com/book/DockerForTheReallyImpatient/Chapter07/06
============
CMD
FROM ubuntu
CMD ["echo", "Hello"]
PS C:\docker> docker image build -t cmd_img -f Dockerfile_cmd .
PS C:\docker> docker container run cmd_img
Hello
근데?
PS C:\docker> docker container run --help
Usage: docker container run [OPTIONS] IMAGE [COMMAND] [ARG...]
Run a command in a new container
:
PS C:\docker> docker container run cmd_img echo World
World
World만 나와
⇐ Dockerfile의 CMD 내용을 container run 명령에서 전달된 명령어로 덮어써서 실행
============
ENTRYPOINT
FROM ubuntu
ENTRYPOINT ["echo", "Hello"]
PS C:\docker> docker image build -t entrypoint_img -f Dockerfile_entrypoint .PS C:\docker> docker container run entrypoint_img
Hello
PS C:\docker> docker container run entrypoint_img echo World
Hello echo World
뒤의 명령어가 인자값으로 사용이 된다
▽그냥 echo Hello echo World가 이어 쓰이나봐?
이렇게 두개가 동작하는 방식이 다르다
ENTRYPOINT는 전달하는게 파라미터값으로 반영 : 컨테이너가 실행될 때 그 명령어가 쓰여야된다고 만드는애가 지정하는 것
CMD는 덮어쓰임 : 경우에 따라 실행되는 명령어가 바뀌어도 되는 경우
'docker' 카테고리의 다른 글
도커 (10)도커컴포즈전, 하나에하나씩, 환경변수, 도커컴포즈, 단일노드, scale (0) 2022.03.01 도커 (9)서브넷마스킹, network (0) 2022.02.26 도커 (7)도커파일 예제 : 리액트, 자바, 스프링부트 (0) 2022.01.26 도커 (6)exec&Up&stop, RUN -y, ADD, EXPOSE, -DFOREGROUND, CMD [ ], &&, build -f (0) 2022.01.26 도커 (5)포그백그, -itd, COMMAND&detach key, -p포트하나만주면 (0) 2022.01.25