python으로 docker 컨트롤하기
새로 시작한 개인 프로젝트는 python기반인데 docker를 이용한 sandbox 아키텍쳐가 필요해졌습니다. 때문에 python으로 작성된 docker client가 필요해서 찾아보니 docker-py를 발견하게 되었습니다. 일반적인 docker 쉘 커맨드와 동일한 기능을 docker-py를 이용해서 거의 모두 사용할 수 있는데 이를 이용해서 python으로는 어떻게 작성하는 지 정리해보겠습니다.
초기화
제일 처음 해야 할 것은 로컬에 있는 docker daemon과 연동해야 하는데 docker-py에서는 Client라는 인스턴스를 생성하고 이에 내재된 다양한 API를 통해 컨트롤이 가능합니다.
from docker import Client
cli = Client()
인자를 주지 않고 인스턴스를 생성하면 기본적으로 로컬로 접근하게 됩니다. base_url
이라는 인자로 외부 daemon과 연동도 가능한 듯 하네요.
docker pull
docker hub에서 이미지를 다운로드합니다.
cli = Client(base_url='tcp://127.0.0.1:2375')
for line in cli.pull('busybox', stream=True):
print(json.dumps(json.loads(line), indent=4))
# { "status": "Pulling image (latest) from busybox", "progressDetail": {}, "id": "e72ac664f4f0" }
# { "status": "Pulling image (latest) from busybox, endpoint: ...", "progressDetail": {}, "id": "e72ac664f4f0" }
인자에 stream=True
로 설정하면 string generator로 리턴되고 False
로 설정하거나 설정하지 않으면 string으로 리턴됩니다.
docker run
docker를 사용하면서 가장 쓰는 명령어가 컨테이너를 기동하는 명령어인 run일텐데요. docker-py에서는 컨테이너를 생성하고(.create_container()
) 시작하는(.start()
) 절차로 진행할 수 있습니다.
container = cli.create_container(image='busybox:latest', command='/bin/sleep 30')
print(container) # {'Id': '8a61192da2b3bb2d922875585e29b74ec0dc4e0117fcbf84c962204e97564cd7', 'Warnings': None}
response = cli.start(container=container.get('Id'))
print(response) # None
command line에서 컨테이너를 기동할 때 다양한 옵션을 줄 수 있는데 자주 쓰는 옵션들만 소개해보겠습니다.
docker run -p
-p, -publish=[]
: 호스트에 연결된 컨테이너의 특정 포트를 외부에 노출합니다. 보통 웹 서버의 포트를 노출할 때 주로 사용합니다.
<호스트 포트>:<컨테이너 포트>
예)-p 80:80
<IP 주소>:<호스트 포트>:<컨테이너 포트>
호스트에 네트워크 인터페이스가 여러 개이거나 IP 주소가 여러 개 일 때 사용합니다. 예)-p 192.168.0.10:80:80
<IP 주소>::<컨테이너 포트>
호스트 포트를 설정하지 않으면 호스트의 포트 번호가 무작위로 설정됩니다. 예)-p 192.168.0.10::80
<컨테이너 포트>
컨테이너 포트만 설정하면 호스트의 포트 번호가 무작위로 설정됩니다. 예)-p 80
docker-py에서는 host_config
를 생성해서 포트 바인딩해줍니다.
container = cli.create_container(
'busybox', 'ls', ports=[1111, 2222],
host_config=cli.create_host_config(port_bindings={
1111: 4567,
2222: None,
3333: [1234, 5678],
})
)
위 코드는 다음과 같이 네트워크 설정을 하게 됩니다.
- 컨테이너 1111번 포트를 호스트 4567번 포트로 bind
- 컨테이너 2222번 포트는 개방하지 않음
- 컨테이너 3333번 포트를 호스트 1234번 포트와 5678번 포트로 bind
포트 바인딩에 대해서 더 자세한 설정은 여기를 참고해주세요.
docker run --link
--link=[]
: 컨테이너끼리 연결합니다.<컨테이너 이름>:<별칭>
형식입니다.
--link="db:db"
포트 바인딩에서 했던 것처럼 host_config
를 생성해서 링크를 설정합니다. 다음 예를 보시죠.
container = cli.create_container(
'busybox', 'ls', ports=[1111, 2222],
host_config=cli.create_host_config(links=[(db_container['Id'], 'db')])
)
이제 busybox 컨테이너 안에서 데이터베이스 컨테이너를 접근할 때 db라는 URL로 접근이 가능합니다. (예: mongo://db:27017
)
docker ps
컨테이너 목록을 출력합니다.
cli.containers()
# [{'Command': '/bin/sleep 30',
# 'Created': 1412574844,
# 'Id': '6e276c9e6e5759e12a6a9214efec6439f80b4f37618e1a6547f28a3da34db07a',
# 'Image': 'busybox:buildroot-2014.02',
# 'Names': ['/grave_mayer'],
# 'Ports': [],
# 'Status': 'Up 1 seconds'}]
docker stop
기동된 컨테이너를 중지합니다.
cli.stop(container.get('id'))
프로젝트를 진행하며 계속 추가하도록 하겠습니다~~ 🙂
프로젝트에서 사용한 것을 위주로 작성하였고, 이 밖에 전체 기능에 대해서는 공식 문서를 참고해주세요.