IT/기초 지식

[Docker/Singularity] Docker, Singularity의 차이

개발자 두더지 2021. 10. 12. 22:19
728x90

Singularity와 Docker의 호환성 문제


 Singularity는 Docker image를 변환하여 Singularity image로써 실행할 수 있는 기능을 가지고 있다. Singularity가 도입되어 있는 머신에서는 no-root로 Docker image를 실행할 수 있다. 그 외에도 Singularity는 명시적으로 마운트를 하지 않아도 현재 디렉토리가 Singularity 컨테이너내의 워크 디렉토리가 되도록 하거나, Docker과 비교하여 파일 시스템의 isolation 제약이 일부 완화되어 있는 등  특정 용도에 따라서는 편리할 때가 많다. 

 하지만, Singularity와 Docker를 동일시하여 다루다가는 다양한 함정에 빠지게 된다. 여기서 몇 가지를 소개하도록 하겠다.

Docker run vs Singularity run

 먼저, Docker run과 Singularity run은 다른 인터페이스로 되어 있음에 주의해야한다. 예를 들어, dockerhub 상에 있는 동일 이미지에 대해 동일한 인수로 실행해도 아래와 같은 차이점이 존재한다.

- Docker상, Dockerfile에서 Entrypoint로 지정하고 잇는 커맨드에 대해서 인수를 전달해 실행하고 싶은 경우

$ docker run --rm <image_name> 1 2 3 4

 - Singularity상, Dockerfile에서 Entrypoint로 지정하고 있는 커맨드에 대해서 인수를 전달하여 실행하고 싶은 경우

$ singularity -s run docker://<image_name_on_docker_hub> 1 2 3 4

- Docker상, Dockerfile에서 Entypoint로 지정하고 있는 커맨드를 무시하고 다른 커맨드를 실행하고 싶은 경우

$ docker run --entrypoint <another_command> --rm <image_name> 1 2 3 4

- Singularity상, Dockerfile에서 Entypoint로 지정하고 있는 커맨드를 무시하고 다른 커맨드를 실행하고 싶은 경우

$ singularity -s exec docker://<image_name_on_docker_hub> <another_command> 1 2 3 4

 이와 같이, 실사용적인 면을 봤을 때, Singularity에서는 run과 exec의 사이에 커맨드의 역할이 분리되어 있음을 알 수 있다.

 다음은 Dockerfile에서 latest를 지정해도, 혹은 docker run에서 latest를 지정하고 있어도, dockerhub를 매번 보러 간다고는 할 수 없고 어디까지나 로컬에 있는 image의 최신 docker image를 이용하고 있는 것에 지나지 않기 때문에, 최신의 dockerhub가 반영되지 않는다. 그에 비해 Singularity는 latest와 태그를 지정하고 있으면 매번 dockerhub에 확인하러 가기 때문에, 최신의 docker image를 바탕으로 singularity image가 구축된다.

 Docker image를 그대로 Singularity에 가져가면 image에 따라 에러가 출력되는 경우가 있다. 예를 들어, neo4j의 docker를 작동시키려고 하면,

$ singularity -s run docker://neo4j:latest

[WARN  tini (15358)] Tini is not running as PID 1 and isn't registered as a child subreaper.
Zombie processes will not be re-parented to Tini, so zombie reaping won't work.
To fix the problem, use the -s option or set the environment variable TINI_SUBREAPER to register Tini as a child subreaper, or run Tini as PID 1.
/docker-entrypoint.sh: line 3: $1: unbound variable

 위와 같은 에러가 발생한다. 개인적인 인상이지만, Singularity에서 완화된 isolation의 제약 때문에, isolation되어있음을 전제로 구축된 Docker image는 그대로 사용할 수 없는 것 같았다. 이것은 이러한 Docker container는 에러를 뱉어내는 것과 같이, 원인을 하나로 특정하는 것이 어려우므로, 시험 삼아 동작시켜 보고 잘 되지 않으면 다시 시작하는 것을 반복해 디버깅하게 된다.

 또한, Entrypoint로 동작하는 Docker내의 스크립트를 기재할 때에도, Singularity에서는 pwd가 마운트되어 있는 것을 상정하지만, Docker의 경우는 그렇지 않다. 양쪽에서 대응하는 스크립트를 쓸 경우에 어떤 디렉토리에 자신이 작동시키고 싶은 데이터가 들어 있는가를 유의하여 작성할 필요가 있다. 예를 들어 Docker image는 WORKDIR에서는 원래 들어있는 데이터가 들어 있고 마운트할 디렉토리는 WORKDIR와 다른 경우에 Singularity에서는 WORKDIR가 마운트되어버리므로 WORKDIR에 원래 들어있는 파일이 사용할 수 없게 되는 경우가 있다.

 

 

Docekrfile을 작성할 때 신경쓰이는 것들


아직 해결하지 못한 문제가 몇 가지 있다.

- build할 때, 임의의 중간 step의 intermediate container를 바탕으로 재실행하는 방법은 없을까?

- 어떤 build image를 사용하면 좋을지 모르겠다. 

실제로는 그 라이브러리 내부에 의존하고 있는 라이브러리나 패키지를 바탕으로, 설치하기 편한 것을 선택한다라는 느낌을 받는다. 한쪽에서 한쪽으로 이동하려고 할 경우에는 Debian과 Alpine에서는 공식 리포지토리로부터 제공되어 있는 패키지명이 다른 경우가 있으므로 주의가 필요하다. 


참고자료

https://sharply.hatenablog.com/entry/2020/03/09/171012

728x90