- 0
- Seia
- 조회 수 569
저도 예전에 그랬지만 많은 사람들이 Docker를 단순히 시스템에 직접 설치 안하고 반가상화해서 ~~를 돌려주는 도구나 혹은 비슷한 정의 그리고 자주하는 보안적인 실수가 있어서 그에 대한 고찰을 적어봅니다.
관련 소스코드 및 기반은 다음 레포지토리에 두고 있습니다.
https://github.com/Seia-Soto/containers
1. 도커 설치: 빌드해야 할까?
가장 먼저 제가 고민한 사항입니다. 어떤 프로그래밍 언어를 배우고 하던 간에 버전 관리자는 필수적이라고 생각합니다. 그래야 호환성 문제를 효과적으로 해결할 수 있기 때문이죠. 하지만 도커는 예외였습니다. 제 생각이지만:
- 도커는 시스템 위에서 동작합니다.
- 대부분의 현대 리눅스 운영체제는 패키지 매니저에서 패키지를 자동으로 설정까지 해줍니다. (대부분 깔끔하게)
2가지 이유로 그냥 패키지 매니저로 설치하는 것을 선호합니다.
2. Docker-Compose와 Swarm, Kube 등, 언제 써야 할까?
언제 Docker-Compose를 써야 할까?
단순하게 멋져보이는 도커 명령어를 입력하는 것보다는 Compose를 사용하면 훨씬 더 효과적으로 프로젝트에 단위를 부여하여 관리할 수 있게 됩니다. 기존에 docker create나 docker run 등으로 직접 컨테이너를 관리하는 것보다 compose를 사용하면:
- 컨테이너를 직접적으로 설명할 수 있게 합니다. (docker-compose.yml)
- 이후 유지보수를 쉽게 합니다.
- 사람 눈에 보기 쉽습니다.
위와 같은 장점이 있다고 생각합니다. 하지만 모든 용도에 Docker-compose가 적합한 것은 아닙니다. Docker-compose도 결국에는 하나의 파이썬 스크립트로 *하나의 메탈*에서 그 능력이 발휘됩니다. 대규모 오케스트레이션이 아닌 홈 서버나 단일 서버에 훨씬 더 적합하다는 뜻입니다. 가장 큰 이유에는 생태계의 다른 도구보다 상대적으로 덜 직관적인 클러스터링 그리고 네트워크 관리 능력에 있습니다. 이는 최근 커뮤니티가 커지고 기술 집약도가 높아지는 Kubernetes(쿠버네테스)를 사용하는 것이 훨씬 더 이후 유지보수에 나을 수 있음을 뜻합니다.
Kubernetes는 대규모 오케스트레이션에서만.
선을 잡아놓으면 편합니다. Kubernetes는 절대로 작은 러닝커브를 가지고 있지 않기 때문입니다. 단순히 네트워크를 잡고 클러스터를 연결하는 것 그 이상으로 설계하는 능력을 필요로 합니다.
Docker-Swarm?
Docker-Swarm이 나쁜 도구는 아닙니다. 하지만 Kube에 밀려 점점 말려들어가는 기술로 커뮤니티의 크기가 상대적으로 굉장히 축소되고 있습니다. 이후에는 Swarm 대신 Kube를 보는 것이 훨씬 나을 것 같습니다. GCP 등의 클라우드 솔루션도 빠르게 제공되고 있고요.
3. Docker-Compose로 홈 서버 관리하기
Docker를 어떻게 쓸까?
먼저 Docker를 왜 쓸까에 대해서 다시 생각해볼 필요가 있습니다. 그 용도에 맞게 써야지 훨씬 더 이후에 스트레스를 줄일 수 있기 때문입니다.
1. 서버 안정성의 강화
가장 먼저 볼 수 있는 것은 안정성 자체가 높아진다는 점입니다. 왜냐하면 격리된 환경에서 애플리케이션을 실행하기 때문입니다. 하지만 단순히 격리를 위해서 도커를 실행하는 것이라면 WASMER로 컴파일하여 단순 격리가 되는 바이너리를 만드는 것을 추천드립니다.
2. 힙해서?
Docker는 힙합니다. 맞아요. 그런데 무조건 언제나 도커를 써야 한다는 말은 아닙니다. 무조건적으로 Docker를 권장하는 이유 중 하나는 위에서 말한 안정성 때문이 큽니다. 실패해도 컨테이너를 다 지우고 OS를 다시 설치할 필요도 없이 데몬만 잘 굴러간다면 처음부터 시작할 수 있기 때문입니다. 하지만 자신의 서버의 목적이 확실하고 Docker가 없어도 충분히 간결하고 강력하게 운영이 되고 있다면 Docker는 짐만 됩니다.
Docker 데몬이 먹는 메모리고 컨테이너고 모두 자원이니 아깝기 때문입니다.
3. 찍먹이 가능하다.
사실 모든 것은 Docker의 가장 큰 특징인 '격리'에서 나옵니다. 동시에 격리가 확실하기 때문에 여러분이 실행하고 싶은게 있다면 바로 돌려줄 수 있습니다.
Docker-Compose를 쓸 때 간과하는 사항
1. 한 개의 프로젝트 단위 당 하나의 네트워크로 묶입니다.
가끔가다가 이런 사람을 본적이 있습니다. 프로젝트 단위(docker-compose.yml) 당 하나의 네트워크로 묶이게 되므로 모든 서비스가 데이터베이스에 연결되기 위해서는 depends_on이든 무엇이든 다 하나의 compose file에 넣어야 하는가 하는 사람입니다. 하지만 단순히 하나의 브릿지 네트워크를 구축하여 사용하는 것이 제일 좋습니다. 굳이 동적인 프로젝트 단위의 네트워크 망을 사용할 이유는 없으니깐요.
docker network create -d bridge <네트워크 이름>
2. 무분별한 ports 사용은 서버에 큰 보안 구멍을 낼 수 있습니다.
두 번재로 더 많은 사람들이 간과하는 부분입니다. 보통 우리는 docker-compose나 docker로 포트를 열려면 -p 혹은 ports를 사용해야 한다는 말을 가볍게 듣고 사용하는 경우가 정말로 흔할 것입니다. 하지만 Docker 데몬은 iptables 규칙을 직접 관리합니다. 사용자가 관여할 필요가 없다는 뜻입니다. 여기에서 관리하다가 한 가지 모순이 생깁니다.
- Docker 트래픽은 Docker 데몬이 관리하는 iptables의 Docker 체인으로 들어갑니다.
즉, 도커로 기존의 스택을 대체할 것이라면 단순한 포트포워딩 등 L3 계층의 작업은 도커 데몬에게 맡기는 것이 훨씬 안정적으로 네트워크를 운용할 수 있게 해줍니다.
이를 해결하기 위해 2가지의 방법을 제시할 수 있습니다. 첫 번째는 컨테이너의 포트를 호스트의 localhost로만 공유되게 하는 것입니다. 아래와 같이 포트 맵핑 앞에 호스트를 작성하여 내부로만 공유되게 할 수 있습니다.
version: "3.8" services: example: build: ./ ports: - "127.0.0.1:80:80"
두 번째는 컨테이너 간의 상호작용을 저희가 위에서 직접 생성한 외부 브릿지 네트워크로 통일하고 expose 프로퍼티를 사용하는 것입니다. 이 경우에는 컨테이너에서 expose에 지정된 포트가 내부 네트워크인 docker_br0 내부에서만 공유되게 됩니다. 즉, 호스트 컴퓨터에서는 포트를 더욱 자유롭게 사용이 가능하다는 것입니다. 원하는 컨테이너에만 ports를 사용하여 외부로 공유되는 포트를 최소화할 수 있습니다.
version: "3.8" services: example: build: ./ expose: - 80 networks: - docker_br0 networks: docker_br0: external: true
*다른 docker 컨테이너에서 접근할 때에는 container_name 프로퍼티를 사용하면 다음에 생성되는 컨테이너에 주소가 자동으로 반영됩니다.
앞으로 더 많아지겠지만 일단은... 그렇습니다.