처음 실행하는 컨테이너에서 실행시키는 스크립트에서 발생할 수 있는 에러...?
컨테이너를 실행시킬 때, 미리 만들어둔 스크립트를 실행시키고 싶은 경우가 있습니다. 이 경우에는 보통 Dockerfile을 만들어서 그 안에 만들어둔 스크립트를 컨테이너에 복사(ADD나 COPY를 이용), 스크립트에 실행 권한 부여(”RUN chmod +u”를 이용), 컨테이너에서 스크립트를 실행(CMD나 ENTRYPOINT를 이용)합니다.
하지만 컨테이너에서 다음과 같은 에러가 발생하는 경우가 있습니다.
standard_init_linux.go:211: exec user process caused "exec format error“
코드의 줄 번호를 나타내는 211은 도커 버전에 따라서 다르게 나타날 수 있습니다.
해당 에러는 컨테이너에서 지정된 파일을 어떤 프로그램을 이용하여 실행해야 하는지 모를 경우 발생할 수 있는 에러입니다. 구체적인 예시로는, 쉘 스크립트 파일을 실행하는 데에, 어떠한 쉘로 실행하는지 모를 경우가 있습니다. 때문에 스크립트 파일에 shebang을 지정해 주든지, Dockerfile에서 어떤 쉘을 이용하여 해당 스크립트를 실행해야 되는지를 지정해 주면 됩니다.
여기서 중요한 것은 바탕이 되는 도커 이미지에 해당 스크립트를 실행 시키는 프로그램이 들어있어야 된다는 것입니다. 예를 들면, alpine에는 bash가 없기 때문에 bash를 설정하면 에러가 발생합니다.
여기서는 그에 대한 테스트를 해 보겠습니다.
사전지식
https://blog.gaerae.com/2015/10/what-is-the-preferred-bash-shebang.html (shebang이란?)
https://docs.docker.com/engine/reference/builder/ (Dockerfile에 대한 설명)
1. 스크립트에 shebang을 넣은 것과 넣지 않은 것으로 테스트
step 1. 스크립트와 Dockerfile을 만듭니다.
(1) shebang을 넣은 스크립트 파일과, 그 파일을 이용하여 Dockerfile을 만듭니다.
[root@centos77 passTest]# cat hello1.sh
#!/bin/bash
echo hello test1!
[root@centos77 passTest]# cat Dockerfile1
FROM ubuntu
ADD ./hello1.sh /tmp/hello1.sh
RUN chmod +x /tmp/hello1.sh
ENTRYPOINT [ "/tmp/hello1.sh" ]
[root@centos77 passTest]#
(2) shebang을 넣지 않은 스크립트 파일과, 그 파일을 이용하여 Dockerfile을 만듭니다.
[root@centos77 passTest]# cat hello2.sh
echo hello test2!
[root@centos77 passTest]# cat Dockerfile2
FROM ubuntu
ADD ./hello2.sh /tmp/hello2.sh
RUN chmod +x /tmp/hello2.sh
ENTRYPOINT [ "/tmp/hello2.sh" ]
[root@centos77 passTest]#
step 2. Dockerfile들을 빌드 시킵니다.
[root@centos77 passTest]# docker build -t test1 -f Dockerfile1 .
Sending build context to Docker daemon 5.12kB
Step 1/4 : FROM ubuntu
---> 1d622ef86b13
Step 2/4 : ADD ./hello1.sh /tmp/hello1.sh
---> 2c6be12f8c9d
Step 3/4 : RUN chmod +x /tmp/hello1.sh
---> Running in 9ae65a2864c5
Removing intermediate container 9ae65a2864c5
---> 9d1b794ef2d3
Step 4/4 : ENTRYPOINT [ "/tmp/hello1.sh" ]
---> Running in 6b0778d8c781
Removing intermediate container 6b0778d8c781
---> 842289f55cff
Successfully built 842289f55cff
Successfully tagged test1:latest
[root@centos77 passTest]# docker build -t test2 -f Dockerfile2 .
Sending build context to Docker daemon 5.12kB
Step 1/4 : FROM ubuntu
---> 1d622ef86b13
Step 2/4 : ADD ./hello2.sh /tmp/hello2.sh
---> 143756c3930c
Step 3/4 : RUN chmod +x /tmp/hello2.sh
---> Running in 506b6cfb1072
Removing intermediate container 506b6cfb1072
---> f86dc3294e15
Step 4/4 : ENTRYPOINT [ "/tmp/hello2.sh" ]
---> Running in 896f63900b89
Removing intermediate container 896f63900b89
---> 9e86009fad13
Successfully built 9e86009fad13
Successfully tagged test2:latest
[root@centos77 passTest]#
step 3. 빌드시킨 이미지를 이용하여 컨테이너를 실행시킵니다.
[root@centos77 passTest]# docker run --rm test1
hello test1!
[root@centos77 passTest]# docker run --rm test2
standard_init_linux.go:211: exec user process caused "exec format error"
[root@centos77 passTest]#
shebang을 넣지 않은 스크립트를 실행시키는 이미지에서는 에러가 발생한 것을 확인할 수 있습니다.
2. Dockerfile에 해당 스크립트를 실행시킬 프로그램을 지정해서 스크립트에 shebang을 넣은 것과 넣지 않은 것으로 테스트
step 0. 위에서 만든 이미지는 제거합니다.
[root@centos77 passTest]# docker rmi test1 test2
Untagged: test1:latest
Deleted: sha256:842289f55cff258a75dea6a8f463762df96a95f78ce55b5a0552c59b2b50559c
Deleted: sha256:9d1b794ef2d329ab12e3c69cf18ba21100be596cb42244fb4706beaed6b6e342
Deleted: sha256:025e51f1c14a68a13928e113a290930afc30d4bc69c978aca30b59f94d2c57dc
Deleted: sha256:2c6be12f8c9df5be89498000ce719cdda0e5463f47970e5764660b0f2704a419
Deleted: sha256:146876ac114558eaeee6739184b4b506e0351d33d205240ffea255898e0e80ae
Untagged: test2:latest
Deleted: sha256:9e86009fad137ec34d1b3dee689a2d6f934f0974cbdb9d13ce52349ba7accc88
Deleted: sha256:f86dc3294e1532ca9b34714ac119415f77bd596f75096588674669f4c219f31f
Deleted: sha256:2e4fc52c8c7e9787552f8ee869caeacf9b0af88537fb2874a30c06d2011b63d3
Deleted: sha256:143756c3930c7994e37c3144d65534bad6a84f02048d8e9bf94544ae94fc3ec0
Deleted: sha256:6b6fc274bd82bdef673692361f154e6db9a33fd61aad83ca75ce0f62cc817e5b
[root@centos77 passTest]#
step 1. 위에서 만든 Dockerfile을 수정합니다.
[root@centos77 passTest]# cat Dockerfile1
FROM ubuntu
ADD ./hello1.sh /tmp/hello1.sh
RUN chmod +x /tmp/hello1.sh
ENTRYPOINT ["sh", "/tmp/hello1.sh" ] # 이부분 수정
[root@centos77 passTest]# cat Dockerfile2
FROM ubuntu
ADD ./hello2.sh /tmp/hello2.sh
RUN chmod +x /tmp/hello2.sh
ENTRYPOINT ["sh", "/tmp/hello2.sh" ] # 이부분 수정
[root@centos77 passTest]#
step 2. 이미지를 빌드합니다.
[root@centos77 passTest]# docker build -t test1 -f Dockerfile1 .
Sending build context to Docker daemon 5.12kB
Step 1/4 : FROM ubuntu
---> 1d622ef86b13
Step 2/4 : ADD ./hello1.sh /tmp/hello1.sh
---> 0f6d1e5af296
Step 3/4 : RUN chmod +x /tmp/hello1.sh
---> Running in 97c158a0d547
Removing intermediate container 97c158a0d547
---> cfaf42284c72
Step 4/4 : ENTRYPOINT ["sh", "/tmp/hello1.sh" ]
---> Running in e37053b9c0d3
Removing intermediate container e37053b9c0d3
---> a4719185de37
Successfully built a4719185de37
Successfully tagged test1:latest
[root@centos77 passTest]# docker build -t test2 -f Dockerfile2 .
Sending build context to Docker daemon 5.12kB
Step 1/4 : FROM ubuntu
---> 1d622ef86b13
Step 2/4 : ADD ./hello2.sh /tmp/hello2.sh
---> b9ddd0d173c1
Step 3/4 : RUN chmod +x /tmp/hello2.sh
---> Running in 1535b9cd3075
Removing intermediate container 1535b9cd3075
---> 44a417a36f67
Step 4/4 : ENTRYPOINT ["sh", "/tmp/hello2.sh" ]
---> Running in c0f3008516a5
Removing intermediate container c0f3008516a5
---> 5f776c498849
Successfully built 5f776c498849
Successfully tagged test2:latest
[root@centos77 passTest]#
step 3. 빌드한 이미지를 이용하여 컨테이너를 실행시킵니다.
[root@centos77 passTest]# docker run --rm test1
hello test1!
[root@centos77 passTest]# docker run --rm test2
hello test2!
[root@centos77 passTest]#
shebang이 없는 스크립트도 실행이 잘 되는 것을 확인할 수 있습니다.
위와 같은 쉘 스크립트 파일 뿐만 아니라, js파일, python파일 에서도 해당 문제가 발생할 경우가 있습니다.
또한, 윈도우에서 만든 쉘 스크립트를 리눅스에서 실행시키려고 할 경우에, 윈도우와 리눅스의 라인의 마지막을 나타내는 문자 코드가 달라서도 이러한 문제가 발생할 수도 있다고 합니다.
참조
https://github.com/containers/buildah/issues/475
https://www.lewuathe.com/exec-format-error-in-docker-container.html