목차
CMD
사용s6-overlay는 설치하기 쉬운(타르볼 한두 개만 추출하면 됩니다!) 스크립트 및 유틸리티 세트로, s6을 서비스의 컨테이너 및 프로세스 감독자를 위한 pid 1로 사용하면서 기존 Docker 이미지를 사용할 수 있게 해줍니다.
다음 Dockerfile을 빌드하고 사용해 보세요.
# Use your favorite image
FROM ubuntu
ARG S6_OVERLAY_VERSION=3.2.0.2
RUN apt-get update && apt-get install -y nginx xz-utils
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
CMD ["/usr/sbin/nginx"]
ADD https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-noarch.tar.xz /tmp
RUN tar -C / -Jxpf /tmp/s6-overlay-noarch.tar.xz
ADD https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-x86_64.tar.xz /tmp
RUN tar -C / -Jxpf /tmp/s6-overlay-x86_64.tar.xz
ENTRYPOINT ["/init"]
docker-host $ docker build -t demo .
docker-host $ docker run --name s6demo -d -p 80:80 demo
docker-host $ docker top s6demo acxf
PID TTY STAT TIME COMMAND
11735 ? Ss 0:00 _ s6-svscan
11772 ? S 0:00 _ s6-supervise
11773 ? Ss 0:00 | _ s6-linux-init-s
11771 ? Ss 0:00 _ rc.init
11812 ? S 0:00 | _ nginx
11814 ? S 0:00 | _ nginx
11816 ? S 0:00 | _ nginx
11813 ? S 0:00 | _ nginx
11815 ? S 0:00 | _ nginx
11779 ? S 0:00 _ s6-supervise
11785 ? Ss 0:00 | _ s6-ipcserverd
11778 ? S 0:00 _ s6-supervise
docker-host $ curl --head http://127.0.0.1/
HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: Mon, 17 Jan 2022 13:33:58 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Mon, 17 Jan 2022 13:32:11 GMT
Connection: keep-alive
ETag: "61e56fdb-264"
Accept-Ranges: bytes
이전 버전의 s6-overlay( v2 )에서 새 버전( v3 )으로 마이그레이션하는 경우 모든 것이 원활하게 작동하려면 서비스나 s6-overlay 사용 방식을 일부 변경해야 할 수도 있습니다. 이 문서는 v3의 작동 방식을 정확하게 설명하려고 노력하지만, 주요 차이점과 눈에 띄는 사항을 나열하는 별도의 페이지가 있습니다. 이런 상황이라면 꼭 읽어보세요!
이 프로젝트에는 다음과 같은 목표가 있습니다.
cont-init.d
), 마무리( cont-finish.d
)와 같은 작업과 이들 간의 종속성이 있는 자체 서비스를 실행할 수 있게 해주는 간단한 init 프로세스입니다.PID 1
기능을 제공합니다.s6
및 s6-portable-utils
에 포함된 전체 유틸리티 세트입니다. 여기에는 우리의 삶을 훨씬 더 쉽게 만들어주는 편리하고 구성 가능한 유틸리티가 포함되어 있습니다.s6-log
사용하는 logutil-service
통해 즉시 사용 가능한 로그 회전.USER
지시문을 일부 지원합니다. 모든 기능과 호환되지는 않습니다. 자세한 내용은 참고 섹션에 나와 있습니다. 자주 반복되는 Docker 주문 중 하나는 "컨테이너당 하나의 프로세스"이지만 우리는 이에 동의하지 않습니다. 컨테이너에서 여러 프로세스를 실행하는 데 본질적으로 나쁜 것은 없습니다. 보다 추상적인 "컨테이너당 한 가지 작업 "이 우리의 정책입니다. 즉, 컨테이너는 "채팅 서비스 실행" 또는 "gitlab 실행"과 같은 한 가지 작업을 수행해야 합니다. 여기에는 여러 프로세스가 포함될 수 있지만 괜찮습니다.
이미지 작성자가 프로세스 감독자를 기피하는 또 다른 이유는 프로세스 감독자가 실패한 서비스를 다시 시작 해야 한다고 믿기 때문입니다. 즉, Docker 컨테이너는 결코 죽지 않을 것입니다.
이는 Docker 생태계를 효과적으로 중단시킵니다. 대부분의 이미지는 오류가 있을 때 종료되는 하나의 프로세스를 실행합니다. 오류 발생 시 종료하면 시스템 관리자가 원하는 대로 오류를 처리할 수 있습니다. 이미지가 종료되지 않는 경우 이제 오류 복구 및 실패 알림을 위한 대체 방법이 필요합니다.
우리의 정책은 "일"이 실패하면 컨테이너도 실패해야 한다는 것입니다. 이를 위해 어떤 프로세스를 다시 시작할 수 있는지, 어떤 프로세스가 컨테이너를 종료해야 하는지 결정합니다. 예를 들어 cron
또는 syslog
실패하면 컨테이너는 아무런 영향 없이 컨테이너를 다시 시작할 수 있지만, ejabberd
실패하면 시스템 관리자가 조치를 취할 수 있도록 컨테이너가 종료되어야 합니다.
"Docker Way"에 대한 우리의 해석은 다음과 같습니다.
우리의 init 시스템은 정확히 그렇게 하도록 설계되었습니다. 이미지는 다른 Docker 이미지처럼 작동하며 기존 이미지 생태계에 적합합니다.
"일" 중지에 대한 자세한 내용은 사용법 섹션 아래의 "선택적 종료 스크립트 작성"을 참조하세요.
우리의 오버레이 초기화는 컨테이너화된 환경에서 적절하게 실행되도록 적절하게 사용자 정의된 것입니다. 이 섹션에서는 단계의 작동 방식을 간략하게 설명하지만 전체 초기화 시스템이 작동하는 방식을 알고 싶다면 s6-svscan을 프로세스 1로 실행하는 방법 문서를 읽어보세요.
/etc/cont-init.d
에 포함된 레거시 원샷 사용자 스크립트를 실행합니다./etc/s6-overlay/s6-rc.d
에 선언된 사용자 s6-rc 서비스를 실행합니다./etc/services.d
)를 임시 디렉터리에 복사하고 s6에서 이를 시작(및 감독)하도록 합니다./etc/cont-finish.d
에 포함된 마무리 스크립트를 실행합니다.TERM
신호를 보냅니다. 어쨌든 남은 프로세스가 없어야합니다.KILL
신호를 보냅니다. 그런 다음 컨테이너가 종료됩니다. s6-overlay는 이미지에 추출할 수 있는 tarball 세트로 제공됩니다. 필요한 타르볼은 사용하는 이미지의 기능입니다. 대부분의 사람들은 처음 두 개가 필요하고 나머지는 편의에 따라 사용할 수 있는 추가 항목입니다.
s6-overlay-noarch.tar.xz
: 이 tarball에는 오버레이를 구현하는 스크립트가 포함되어 있습니다. 아키텍처에 독립적이기 때문에 "noarch"라고 부릅니다. 스크립트와 기타 텍스트 파일만 포함되어 있습니다. s6-overlay를 실행하려는 모든 사람은 이 tarball을 추출해야 합니다.s6-overlay-x86_64.tar.xz
: x86_64
시스템 아키텍처로 바꿉니다. 이 타르볼에는 s6 생태계에서 필요한 모든 바이너리가 포함되어 있으며 모두 정적으로 연결되어 이미지 바이너리를 방해하지 않습니다. 오버레이에 사용되는 바이너리를 제공하는 모든 패키지가 이미지에 이미 포함되어 있는지 확실히 알지 못하는 경우에는 이 타르볼을 추출해야 합니다.s6-overlay-symlinks-noarch.tar.xz
: 이 타르볼에는 s6-overlay 스크립트에 대한 심볼릭 링크가 포함되어 있으므로 /usr/bin
통해 액세스할 수 있습니다. 일반적으로 필요하지 않으며 PATH 환경 변수를 통해 모든 스크립트에 액세스할 수 있지만 #!/usr/bin/with-contenv
와 같은 shebang이 포함된 이전 사용자 스크립트가 있는 경우 이러한 심볼릭 링크를 설치하면 작동합니다.s6-overlay-symlinks-arch.tar.xz
: 이 타르볼에는 두 번째 타르볼에서 제공하는 s6 생태계의 바이너리에 대한 심볼릭 링크가 포함되어 있어 /usr/bin
통해 액세스할 수 있습니다. 일반적으로 필요하지 않지만 #!/usr/bin/execlineb
와 같은 shebang이 포함된 이전 사용자 스크립트가 있는 경우 이러한 심볼릭 링크를 설치하면 작동합니다.syslogd-overlay-noarch.tar.xz
: 이 tarball에는 syslogd
서비스에 대한 정의가 포함되어 있습니다. s6 로깅 인프라를 활용하기 위해 stderr에 로그할 수 없는 데몬을 실행 중이지만 이전 syslog()
메커니즘을 사용하여 하드코딩한 경우 이 tarball을 추출할 수 있으며 컨테이너는 syslogd
데몬의 경량 에뮬레이션을 실행합니다. 따라서 syslog 로그가 포착되어 디스크에 저장됩니다.해당 tarball을 설치하려면 설치하려는 기능에 해당하는 Dockerfile에 줄을 추가하세요. 예를 들어 대부분의 사람들은 다음을 사용합니다.
ADD https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-noarch.tar.xz /tmp
RUN tar -C / -Jxpf /tmp/s6-overlay-noarch.tar.xz
ADD https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-x86_64.tar.xz /tmp
RUN tar -C / -Jxpf /tmp/s6-overlay-x86_64.tar.xz
추출할 때 파일 권한을 유지해야 합니다(즉, tar
에 -p
옵션을 사용하는 경우).
프로젝트는 이미지 루트에서 추출한 표준 .tar.xz 파일 세트로 배포됩니다. ( .tar.xz
파일을 이해하려면 tar
용 xz-utils 패키지가 필요합니다. 모든 배포판에서 사용할 수 있지만 항상 기본 컨테이너 이미지에 있는 것은 아니므로 apt install xz-utils
또는 apk add xz
가 필요할 수도 있습니다. 아카이브를 확장하기 전에는 이에 상응합니다.)
그런 다음 ENTRYPOINT
/init
로 설정하세요.
지금은 RUN
지시문에서 wget
또는 curl
실행하는 대신 Docker의 ADD
지시문을 사용하는 것이 좋습니다. ADD
사용할 때 Docker는 https URL을 처리할 수 있는 반면, 기본 이미지는 https를 사용하지 못하거나 사용하지 못할 수도 있습니다. wget
또는 curl
전혀 설치되지 않았습니다.
여기에서 다음과 같은 몇 가지 옵션을 선택할 수 있습니다.
CMD
로 실행하세요.CMD
사용 CMD
사용하는 것은 오버레이를 활용하는 편리한 방법입니다. CMD
빌드 시 Dockerfile에서 제공되거나 런타임 시 명령줄에서 제공될 수 있습니다. 어느 쪽이든 괜찮습니다. s6에서 설정한 환경에서는 일반 프로세스로 실행됩니다. 실패하거나 종료되면 컨테이너는 완전히 종료되고 종료됩니다. 이러한 방식으로 대화형 프로그램을 실행할 수 있습니다. CMD만 대화형 명령을 수신하고 지원 프로세스는 영향을 받지 않습니다.
예를 들어:
FROM busybox
ADD https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-noarch.tar.xz /tmp
RUN tar -C / -Jxpf /tmp/s6-overlay-noarch.tar.xz
ADD https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-x86_64.tar.xz /tmp
RUN tar -C / -Jxpf /tmp/s6-overlay-x86_64.tar.xz
ENTRYPOINT ["/init"]
docker-host $ docker build -t s6demo .
docker-host $ docker run -ti s6demo /bin/sh
/package/admin/s6-overlay/libexec/preinit: notice: /var/run is not a symlink to /run, fixing it
s6-rc: info: service s6rc-oneshot-runner: starting
s6-rc: info: service s6rc-oneshot-runner successfully started
s6-rc: info: service fix-attrs: starting
s6-rc: info: service fix-attrs successfully started
s6-rc: info: service legacy-cont-init: starting
s6-rc: info: service legacy-cont-init successfully started
s6-rc: info: service legacy-services: starting
s6-rc: info: service legacy-services successfully started
/ # ps
PID USER TIME COMMAND
1 root 0:00 /package/admin/s6/command/s6-svscan -d4 -- /run/service
17 root 0:00 {rc.init} /bin/sh -e /run/s6/basedir/scripts/rc.init top /bin/sh
18 root 0:00 s6-supervise s6-linux-init-shutdownd
20 root 0:00 /package/admin/s6-linux-init/command/s6-linux-init-shutdownd -c /run/s6/basedir -g 3000 -C -B
24 root 0:00 s6-supervise s6rc-fdholder
25 root 0:00 s6-supervise s6rc-oneshot-runner
31 root 0:00 /package/admin/s6/command/s6-ipcserverd -1 -- /package/admin/s6/command/s6-ipcserver-access -v0 -E -l0 -i data/rules -- /packa
58 root 0:00 /bin/sh
66 root 0:00 ps
/ # exit
s6-rc: info: service legacy-services: stopping
s6-rc: info: service legacy-services successfully stopped
s6-rc: info: service legacy-cont-init: stopping
s6-rc: info: service legacy-cont-init successfully stopped
s6-rc: info: service fix-attrs: stopping
s6-rc: info: service fix-attrs successfully stopped
s6-rc: info: service s6rc-oneshot-runner: stopping
s6-rc: info: service s6rc-oneshot-runner successfully stopped
docker-host $
s6 오버레이가 포함된 컨테이너를 사용하는 다른 방법은 서비스를 감독하는 것입니다. 귀하는 원하는 만큼의 서비스를 감독할 수 있습니다. 일반적으로 CMD로 실행하는 기본 데몬에 대한 지원 서비스일 뿐이지만, 원하는 경우 빈 CMD를 갖고 기본 데몬을 감독 서비스로 실행하는 것을 막을 수 있는 방법은 없습니다. 이 경우 데몬은 종료될 때마다 s6에 의해 다시 시작됩니다. 컨테이너는 docker stop
명령을 통해 또는 컨테이너 내부에서 /run/s6/basedir/bin/halt
명령을 사용하여 그렇게 하도록 지시한 경우에만 중지됩니다.
감독 서비스를 만드는 방법에는 두 가지가 있습니다. 여전히 지원되는 기존 방식은 "순수한 s6" 서비스 디렉터리를 만드는 것입니다. /etc/services.d
에 서비스 이름으로 디렉터리를 만들고 여기에 실행 가능한 run
파일을 넣습니다. 이것은 오랫동안 지속되는 프로세스 실행을 저장할 파일입니다. 서비스 디렉터리 감독에 대한 자세한 내용과 s6에서 데몬을 처리하는 방법을 구성하는 방법은 servicedir 문서를 참조하세요. 간단한 예는 다음과 같습니다:
/etc/services.d/myapp/run
:
#!/command/execlineb -P
nginx -g "daemon off;"
새로운 방법은 /etc/s6-overlay/s6-rc.d
디렉토리에 s6-rc 소스 정의 디렉토리를 만들고 해당 디렉토리의 이름을 user
번들에 추가하는 것입니다. 즉, 동일한 이름의 빈 파일을 생성합니다. /etc/s6-overlay/s6-rc.d/user/contents.d
디렉토리에 있습니다. 소스 정의 디렉터리 의 형식은 이 페이지에 설명되어 있습니다. /etc/services.d
메소드와 마찬가지로 s6에 의해 감독되는 데몬인 longruns를 정의할 수 있지만 oneshots , 즉 한 번 실행되고 종료되는 프로그램도 정의할 수 있습니다. 귀하의 주요 서비스는 아마도 일회성 서비스가 아닌 장기 서비스 일 것입니다. 아마도 계속 유지하려면 데몬이 필요할 것입니다.
이 새로운 형식의 장점은 서비스 간의 종속성을 정의할 수 있다는 것입니다. B가 A 에 의존하는 경우 A 가 먼저 시작되고 A 가 준비되면 B 가 시작되며 컨테이너가 종료하라는 지시를 받으면 B는 중지됩니다. 먼저, 그 다음에는 A 입니다 . 다양한 프로세스가 서로 의존하는 복잡한 아키텍처가 있거나 단순히 원샷 과 롱런을 정확한 순서로 혼합해야 하는 경우 이것이 적합할 수 있습니다.
위의 예는 다음과 같이 다시 작성할 수 있습니다.
/etc/s6-overlay/s6-rc.d/myapp/type
:
longrun
/etc/s6-overlay/s6-rc.d/myapp/run
:
#!/command/execlineb -P
nginx -g "daemon off;"
/etc/s6-overlay/s6-rc.d/user/contents.d/myapp
: 빈 파일. (이렇게 하면 컨테이너 부팅 시 s6-rc가 시작되는 서비스 세트에 myapp
추가됩니다.)
/etc/s6-overlay/s6-rc.d/myapp/dependencies.d/base
: 빈 파일. (이것은 모든 기본 서비스가 준비되었을 때만 myapp
시작하도록 s6-rc에 지시합니다. 이는 경쟁 조건을 방지합니다.)
새로운 형식으로 전환하는 것이 좋지만, 그 이점이 필요하지 않은 경우 /etc/services.d
의 일반 서비스 디렉터리를 그대로 사용하면 잘 작동합니다.
기본 서비스를 CMD로 실행하는 경우에는 아무 작업도 수행할 수 없습니다. CMD가 종료되거나 docker stop
실행할 때 컨테이너는 자연스럽게 서비스와 동일한 종료 코드로 종료됩니다. (그러나 docker stop
의 경우 서비스는 SIGTERM을 받게 됩니다. 이 경우 종료 코드는 서비스가 처리하는 방법에 전적으로 의존합니다. 이를 트랩하고 0을 종료하거나 트랩하고 다른 것을 종료할 수 있습니다. , 또는 트랩하지 않고 쉘이 자체 코드를 종료하도록 합니다. 일반적으로 130입니다.)
그러나 기본 서비스를 감독되는 서비스로 실행하는 경우에는 상황이 다르며 docker stop
명령을 보낼 때 종료할 코드를 컨테이너에 알려야 합니다. 그렇게 하려면 finish
스크립트를 작성해야 합니다.
/etc/services.d
의 레거시 서비스인 경우 실행 가능한 /etc/services.d/myapp/finish
스크립트가 필요합니다./etc/s6-overlay/s6-rc.d/myapp/finish
파일이 필요합니다(파일은 실행 가능하거나 실행 가능하지 않을 수 있음). 이 finish
스크립트는 서비스가 종료될 때 실행되며 다음 두 가지 인수를 사용합니다.
finish
스크립트에서 /run/s6-linux-init-container-results/exitcode
파일에 원하는 컨테이너 종료 코드를 작성해야 합니다. 그게 전부입니다.
예를 들어 위의 myapp
서비스에 대한 finish
스크립트는 다음과 같을 수 있습니다.
#! /bin/sh
if test " $1 " -eq 256 ; then
e= $(( 128 + $2 ))
else
e= " $1 "
fi
echo " $e " > /run/s6-linux-init-container-results/exitcode
컨테이너에 docker stop
명령을 보내면 myapp
서비스가 종료되고 이 스크립트가 실행됩니다. myapp
의 종료 코드( myapp
TERM 신호를 포착하는 경우) 또는 130( myapp
TERM 신호를 포착하지 못하는 경우)을 특수 /run/s6-linux-init-container-results/exitcode
파일에 기록합니다. 컨테이너 종료 절차가 끝나면 s6-overlay에서 읽을 수 있으며 컨테이너는 해당 값으로 종료됩니다.
이 섹션에서는 v3 이전 버전의 s6-overlay 기능에 대해 설명합니다. fix-attrs는 v3에서 계속 지원되지만 여러 가지 이유로 더 이상 사용 되지 않습니다. 그 중 하나는 정적으로 소유권을 변경할 수 있는데 동적으로 소유권을 변경하는 것은 일반적으로 좋은 정책이 아니라는 것입니다. 또 다른 이유는 USER 컨테이너에서는 작동하지 않는다는 것입니다. 이제 fix-attrs 대신 컨테이너를 실행하기 전에 오프라인으로 호스트 마운트에 대한 소유권과 권한을 관리하는 것이 좋습니다. 필요한 정보가 모두 있으면 Dockerfile에서 이 작업을 수행해야 합니다.
즉, 이전 버전에 대해 작성한 내용은 다음과 같습니다. 이는 오늘날에도 여전히 적용 가능합니다(하지만 이에 의존하지 마세요).
예를 들어 컨테이너 내부에 호스트 폴더를 마운트/매핑했기 때문에 계속하기 전에 소유권 및 권한을 수정하는 것이 흥미로운 경우가 있습니다. 오버레이는 /etc/fix-attrs.d
에 있는 파일을 사용하여 이 문제를 해결하는 방법을 제공합니다. 다음은 fix-attrs 파일이 뒤따르는 패턴 형식입니다.
path recurse account fmode dmode
path
: 파일 또는 디렉터리 경로입니다.recurse
: ( true
또는 false
로 설정) 폴더가 발견되면 그 안에 포함된 모든 파일 및 폴더를 반복합니다.account
: 대상 계정입니다. 계정을 찾을 수 없는 경우 대체 uid:gid
기본값으로 설정할 수 있습니다. 예를 들어, nobody,32768:32768
먼저 nobody
계정을 사용하려고 시도한 다음 대신 uid 32768
로 대체합니다. 예를 들어 daemon
계정이 UID=2
및 GID=2
인 경우 account
필드에 가능한 값은 다음과 같습니다.daemon: UID=2 GID=2
daemon,3:4: UID=2 GID=2
2:2,3:4: UID=2 GID=2
daemon:11111,3:4: UID=2 GID=11111
11111:daemon,3:4: UID=11111 GID=2
daemon:daemon,3:4: UID=2 GID=2
daemon:unexisting,3:4: UID=2 GID=4
unexisting:daemon,3:4: UID=3 GID=2
11111:11111,3:4: UID=11111 GID=11111
fmode
: 대상 파일 모드. 예를 들어 0644
입니다.dmode
: 대상 디렉터리/폴더 모드입니다. 예를 들어 0755
입니다.다음은 몇 가지 실제 사례입니다.
/etc/fix-attrs.d/01-mysql-data-dir
:
/var/lib/mysql true mysql 0600 0700
/etc/fix-attrs.d/02-mysql-log-dirs
:
/var/log/mysql-error-logs true nobody,32768:32768 0644 2700
/var/log/mysql-general-logs true nobody,32768:32768 0644 2700
/var/log/mysql-slow-query-logs true nobody,32768:32768 0644 2700
이를 수행하는 오래된 방법은 다음과 같습니다.
속성을 수정한 후( /etc/fix-attrs.d/
통해) 사용자 제공 서비스를 시작하기 전에( s6-rc 또는 /etc/services.d
통해) 오버레이는 /etc/cont-init.d
예를 들면 다음과 같습니다.
/etc/cont-init.d/02-confd-onetime
:
#!/command/execlineb -P
with-contenv
s6-envuidgid nginx
multisubstitute
{
import -u -D0 UID
import -u -D0 GID
import -u CONFD_PREFIX
define CONFD_CHECK_CMD "/usr/sbin/nginx -t -c {{ .src }}"
}
confd --onetime --prefix="${CONFD_PREFIX}" --tmpl-uid="${UID}" --tmpl-gid="${GID}" --tmpl-src="/etc/nginx/nginx.conf.tmpl" --tmpl-dest="/etc/nginx/nginx.conf" --tmpl-check-cmd="${CONFD_CHECK_CMD}" etcd
이 방법은 여전히 지원됩니다. 그러나 이제는 보다 일반적이고 효율적인 방법이 있습니다. 즉, 일회성 초기화 및 마무리 작업을 s6-rc 서비스로 작성하고 /etc/s6-overlay/s6-rc.d
에 서비스 정의 디렉터리를 추가하여 이를 일부로 만드는 것입니다. user
번들(컨테이너가 부팅될 때 실제로 시작됨) 및 base
번들에 종속되도록 만듭니다(따라서 base
이후에만 시작됨).
s6-rc에 대한 모든 정보는 여기에서 확인할 수 있습니다.
컨테이너가 시작되면 작업은 다음 순서로 수행됩니다.
/etc/fix-attrs.d
의 파일에 따라 수행됩니다./etc/cont-init.d
의 원샷 초기화 스크립트는 순차적으로 실행됩니다.user
번들의 서비스는 종속성에 정의된 순서대로 s6-rc에 의해 시작됩니다. 서비스는 일회성(초기화 작업) 또는 장기 실행(컨테이너의 수명 동안 실행되는 데몬)일 수 있습니다. 서비스가 base
에 의존하는 경우 서비스는 더 일찍 시작되지 않고 이 시점에서 시작되도록 보장됩니다. 그렇지 않은 경우 더 일찍 시작되었을 수 있으며 이로 인해 경쟁 조건이 발생할 수 있습니다. 따라서 항상 base
에 종속되도록 만드는 것이 좋습니다./etc/services.d
의 Longrun 서비스가 시작됩니다.user2
번들의 서비스가 시작됩니다. (대부분의 사람들은 이것을 사용할 필요가 없습니다. 확실하지 않은 경우 user
번들을 고수하십시오.)관리자가 중지 명령을 보냈거나 CMD가 종료되어 컨테이너가 중지되면 작업은 역순으로 수행됩니다.
user2
번들의 서비스가 중지됩니다./etc/services.d
의 Longrun 서비스가 중지되었습니다.down
스크립트가 실행된다는 의미입니다. 이것이 s6-rc가 마무리 작업을 수행하는 방법입니다./etc/cont-finish.d
의 원샷 마무리 스크립트가 순차적으로 실행됩니다. user2
번들의 요점은 여기에 선언된 사용자 서비스가 /etc/services.d
서비스 이후에 시작되도록 허용하는 것입니다. 하지만 그렇게 하려면 user2
의 모든 서비스가 legacy-services
에 대한 종속성을 선언해야 합니다. 즉, foobar
서비스를 늦게 시작하려면 다음을 수행해야 합니다.
/etc/s6-overlay/s6-rc.d/foobar
에 정의하세요./etc/s6-overlay/s6-rc.d/foobar/dependencies.d/legacy-services
파일 추가/etc/s6-overlay/s6-rc.d/user2/contents.d/foobar
파일을 추가합니다. 그러면 foobar
/etc/services.d
의 모든 항목 이후에 시작됩니다.
기본적으로 /etc/services.d
에 생성된 서비스는 자동으로 다시 시작됩니다. 서비스가 컨테이너를 중단해야 하는 경우 대신 CMD로 실행해야 할 수 있습니다. 그러나 감독되는 서비스로 실행하려면 서비스가 중단될 때 실행될 finish
스크립트를 작성해야 합니다. 컨테이너를 중지하려면 /run/s6/basedir/bin/halt
명령을 호출해야 합니다. 다음은 종료 스크립트의 예입니다.
/etc/services.d/myapp/finish
:
#!/command/execlineb -S0
foreground { redirfd -w 1 /run/s6-linux-init-container-results/exitcode echo 0 }
/run/s6/basedir/bin/halt
스크립트의 첫 번째 줄은 /run/s6-linux-init-container-results/exitcode
파일에 0
씁니다. 두 번째 줄은 컨테이너를 중지합니다. 컨테이너 내부에서 실행되는 /run/s6/basedir/bin/halt
명령을 통해 컨테이너를 중지하면 /run/s6-linux-init-container-results/exitcode
읽히고 해당 내용이 종료 코드로 사용됩니다. 컨테이너를 시작한 docker run
명령. 파일이 존재하지 않거나 docker stop
또는 다른 이유로 컨테이너가 중지된 경우 해당 종료 코드의 기본값은 0입니다.
종료 스크립트에서는 더 많은 고급 작업을 수행할 수 있습니다. 예를 들어, 다음은 0이 아닌 값으로 종료될 때만 서비스를 종료하는 스크립트입니다.
/etc/services.d/myapp/finish
:
#!/command/execlineb -S1
if { eltest ${1} -ne 0 -a ${1} -ne 256 }
/run/s6/basedir/bin/halt
일반적으로 종료 스크립트는 데몬이 종료된 후 로컬 정리에만 사용해야 합니다. 서비스가 너무 중요해서 컨테이너가 종료될 때 중지해야 하는 경우 해당 서비스를 CMD로 실행하는 것이 좋습니다.
모든 서비스에는 전용 로거가 있을 수 있습니다. 로거는 서비스의 stdout 에서 자동으로 읽고 원하는 위치의 자동 회전된 파일에 데이터를 기록하는 s6 서비스입니다. 데몬은 일반적으로 stdout이 아닌 stderr에 기록하므로 stderr을 포착하려면 셸에서 exec 2>&1
사용하거나 execline에서 fdmove -c 2 1
사용하여 서비스 실행 스크립트를 시작해야 합니다.
s6-overlay는 s6-log
프로그램에 대한 래퍼인 logutil-service
라는 유틸리티를 제공합니다. 이 도우미는 다음을 수행합니다.
S6_LOGGING_SCRIPT
에 포함된 로깅 스크립트를 어떻게 계속 읽어야 하는지 읽어보세요.nobody
사용자에게 권한을 삭제합니다(존재하지 않는 경우 기본값은 65534:65534
). 그러면 s6-log는 영원히 실행되어 서비스에서 데이터를 읽고 이를 logutil-service
에 지정한 디렉터리에 씁니다.
참고:
s6-setuidgid
사용하여 사용자를 전환할 필요가 없습니다.nobody
사용자가 쓸 수 있습니다.nobody
사용자가 쓸 수 있습니다. cont-init.d
스크립트에서 또는 s6-rc 원샷으로 로그 폴더를 생성할 수 있습니다. 다음은 이전 방식으로 구현된 기록된 서비스 myapp
의 예입니다.
/etc/cont-init.d/myapp-log-prepare
:
#! /bin/sh -e
mkdir -p /var/log/myapp
chown nobody:nogroup /var/log/myapp
chmod 02755 /var/log/myapp
/etc/services.d/myapp/run
:
#! /bin/sh
exec 2>&1
exec mydaemon-in-the-foreground-and-logging-to-stderr
/etc/services.d/myapp/log/run
:
#! /bin/sh
exec logutil-service /var/log/myapp
그리고 여기에는 s6-rc에 구현된 동일한 서비스인 myapp이 있습니다.
/etc/s6-overlay/s6-rc.d/myapp-log-prepare/dependencies.d/base
: 빈 파일
/etc/s6-overlay/s6-rc.d/myapp-log-prepare/type
:
oneshot
/etc/s6-overlay/s6-rc.d/myapp-log-prepare/up
:
if { mkdir -p /var/log/myapp }
if { chown nobody:nogroup /var/log/myapp }
chmod 02755 /var/log/myapp
(상세 섹션의 시작 부분입니다.)
따라서 up
및 down
파일은 특별합니다. 이는 쉘 스크립트가 아니라 execlineb에 의해 해석되는 단일 명령줄입니다. execline에 대해 걱정할 필요가 없습니다. up
파일에는 단일 명령줄이 포함되어 있다는 점만 기억하면 됩니다. 따라서 여러 지침이 포함된 스크립트가 필요한 경우 수행 방법은 다음과 같습니다.
up
파일에서 해당 스크립트를 호출하십시오. myapp-log-prepare
에 대한 up
파일 작성을 일반적으로 진행하는 방법은 다음과 같습니다.
/etc/s6-overlay/s6-rc.d/myapp-log-prepare/up
:
/etc/s6-overlay/scripts/myapp-log-prepare
/etc/s6-overlay/scripts/myapp-log-prepare
: (실행 가능해야 함)
#! /bin/sh -e
mkdir -p /var/log/myapp
chown nobody:nogroup /var/log/myapp
chmod 02755 /var/log/myapp
실제 스크립트의 위치는 임의적이며 up
파일에 작성 중인 내용과 일치하면 됩니다.
그러나 여기서는 스크립트가 너무 복잡하거나 이해하기 어렵게 만들지 않고 up
파일에 완전히 들어갈 수 있을 만큼 간단합니다. 따라서 우리는 원하는 경우 파일로 더 많은 작업을 up
할 수 있음을 보여주기 위해 이를 예로 포함하기로 결정했습니다. 여기에서 execline 언어에 대한 전체 문서를 읽을 수 있습니다.
(상세 섹션이 끝나면 위의 삼각형을 다시 클릭하면 접힙니다.)
/etc/s6-overlay/s6-rc.d/myapp/dependencies.d/base
: 빈 파일
/etc/s6-overlay/s6-rc.d/myapp-log/dependencies.d/myapp-log-prepare
: 빈 파일
/etc/s6-overlay/s6-rc.d/myapp/type
:
longrun
/etc/s6-overlay/s6-rc.d/myapp/run
:
#! /bin/sh
exec 2>&1
exec mydaemon-in-the-foreground-and-logging-to-stderr
/etc/s6-overlay/s6-rc.d/myapp/producer-for
:
myapp-log
/etc/s6-overlay/s6-rc.d/myapp-log/type
:
longrun
/etc/s6-overlay/s6-rc.d/myapp-log/run
:
#! /bin/sh
exec logutil-service /var/log/myapp
/etc/s6-overlay/s6-rc.d/myapp-log/consumer-for
:
myapp
/etc/s6-overlay/s6-rc.d/myapp-log/pipeline-name
:
myapp-pipeline
/etc/s6-overlay/s6-rc.d/user/contents.d/myapp-pipeline
: 빈 파일
파일이 너무 많아요! 이것이 의미하는 바를 요약하면 다음과 같습니다.
myapp | myapp-log
파이프라인에는 myapp-pipeline
이름이 지정되고 이 이름은 user
번들의 일부로 선언되므로 컨테이너가 시작될 때 시작됩니다.myapp-log-prepare
, myapp-log
및 myapp
모두 base
번들에 의존합니다. 즉, 시스템이 실제로 시작할 준비가 된 경우에만 시작됩니다. 이는 실제로 /etc/cont-init.d
및 /etc/services.d
메소드와 동일한 작업을 수행하지만 그 아래가 훨씬 더 깔끔하고 훨씬 더 복잡한 종속성 그래프를 처리할 수 있으므로 기회가 있을 때마다 다음을 권장합니다. 서비스와 로거를 선언하는 s6-rc 방식에 익숙해졌습니다. 서비스가 장기 실행인지 일회성인지 선언, 파이프라인 선언, 필요한 경우 서비스별 제한 시간 추가 등을 포함한 서비스 정의 디렉터리의 전체 구문은 여기에서 찾을 수 있습니다.
서비스 실행과 관련하여 서비스인지 로거인지에 관계없이 실행하기 전에 권한을 삭제하는 것이 좋습니다. s6
에는 다음과 같은 작업을 수행하는 유틸리티가 이미 포함되어 있습니다.
execline
중 :
#!/command/execlineb -P
s6-setuidgid daemon
myservice
sh
에서 :
#! /bin/sh
exec s6-setuidgid daemon myservice
이러한 유틸리티에 대해 더 자세히 알고 싶다면 s6-setuidgid
, s6-envuidgid
및 s6-applyuidgid
를 살펴보세요.
사용자 정의 스크립트에서 컨테이너 환경을 사용할 수 있도록 하려면 with-contenv
도우미를 사용하면 모든 항목을 실행 환경으로 푸시할 수 있습니다. 예를 들면 다음과 같습니다.
/etc/cont-init.d/01-contenv-example
:
#! /command/with-contenv sh
env
이 스크립트는 컨테이너 환경의 콘텐츠를 출력합니다.
최신 버전의 Docker에서는 읽기 전용 루트 파일 시스템으로 컨테이너를 실행할 수 있습니다. 컨테이너가 이러한 경우에 해당하는 경우 S6_READ_ONLY_ROOT=1
설정하여 s6-overlay에 특정 영역에 쓰기를 시도하지 말아야 함을 알려야 합니다. 대신 /run
에 마운트된 tmpfs에 복사를 수행합니다.
s6-overlay는 다음을 가정합니다.
/run
존재하며 쓰기 가능합니다. 그렇지 않은 경우 해당 위치에 tmpfs를 마운트하려고 시도합니다./var/run
이전 버전과의 호환성을 위해 /run
에 대한 심볼릭 링크입니다. 그렇지 않다면 그렇게 만들 것입니다. 일반적으로 기본 docker 설정은 이미 /run
에 적합한 tmpfs를 제공해야 합니다.
이미 사전 정의된 환경 변수 세트를 실행 컨텍스트에 제공하여 s6-overlay의 동작을 조정하는 것이 가능합니다.
PATH
(기본값 = /command:/usr/bin:/bin
): 이는 CMD를 포함하여 컨테이너의 모든 서비스가 갖게 될 기본 PATH입니다. 다른 디렉토리(예: /usr/sbin
에 저장된 바이너리에 의존하는 서비스가 많은 경우 이 변수를 설정하십시오. /command
, /usr/bin
및 /bin
사용자가 제공한 경로에 아직 없는 경우 항상 해당 경로에 추가됩니다.S6_KEEP_ENV
(기본값 = 0): 설정되면 환경이 재설정되지 않고 전체 감독 트리가 원래 환경 변수 세트를 봅니다. with-contenv
nop으로 전환합니다.S6_LOGGING
(기본값 = 0):0
: 모든 것을 stdout/stderr로 출력합니다.1
: 내부 catch-all
로거를 사용하고 모든 내용을 유지하며 /var/log/s6-uncaught-logs
에 있습니다. CMD
로 실행되는 모든 항목은 여전히 stdout/stderr로 출력됩니다.2
: 내부 catch-all
로거를 사용하고 CMD
출력을 포함하여 모든 것을 유지합니다. stdout/stderr에는 아무 것도 기록되지 않습니다.S6_CATCHALL_USER
(기본값 = 루트): 설정되어 있고 S6_LOGGING
이 1 또는 2이면 포괄 로거가 이 사용자로 실행됩니다. 이 사용자는 이미지의 /etc/passwd
에 정의되어야 합니다. 모든 권한 분리는 보안에 약간의 도움이 됩니다.S6_BEHAVIOUR_IF_STAGE2_FAILS
(기본값 = 0): 서비스 스크립트 중 하나가 실패할 경우 컨테이너가 수행해야 하는 작업을 결정합니다. 여기에는 다음이 포함됩니다.fix-attrs
에서 오류가 발생하는 경우/etc/cont-init.d
또는 새로운 스타일의 s6-rc 원샷이 실패하는 경우/etc/services.d
또는 새로운 스타일의 s6-rc longrun이 준비 알림을 예상하는 것으로 표시되고 할당된 시간 내에 준비가 되지 않는 경우(아래 S6_CMD_WAIT_FOR_SERVICES_MAXTIME
참조) S6_BEHAVIOUR_IF_STAGE2_FAILS
의 유효한 값은 다음과 같습니다.0
: 스크립트가 실패하더라도 자동으로 계속합니다.1
: 계속하지만 귀찮은 오류 메시지와 함께 경고합니다.2
: 컨테이너를 중지합니다.S6_KILL_FINISH_MAXTIME
(기본값 = 5000): 종료 시 /etc/cont-finish.d
의 스크립트가 자연스럽게 완료될 때까지 시스템이 기다려야 하는 시간(밀리초)입니다. 이 기간이 지나면 스크립트에 SIGKILL이 전송됩니다. /etc/cont.finish.d
의 스크립트는 순차적으로 실행되며 종료 시퀀스는 잠재적으로 각 스크립트에 대해 S6_KILL_FINISH_MAXTIME
밀리초 동안 대기합니다.S6_SERVICES_READYTIME
(기본값 = 50): /etc/services.d
에 선언된 서비스를 사용하면 서비스가 시작되는 순간과 준비 상태를 테스트할 수 있는 순간 사이에 피할 수 없는 경쟁 조건이 있습니다. 이러한 경쟁을 피하기 위해 우리는 준비 상태를 테스트하기 전에 기본적으로 50밀리초의 약간의 시간을 자게 됩니다. 컴퓨터가 느리거나 매우 바쁜 경우 s6-svwait: fatal: unable to s6_svstatus_read: No such file or directory
와 같은 오류가 발생할 수 있습니다. 이 경우 S6_SERVICES_READYTIME
변수에 수면 시간을 선언하여(밀리초 단위) 늘려야 합니다. 이는 /etc/services.d
에만 관련된다는 점에 유의하세요. s6-rc는 경쟁 조건에 영향을 받지 않습니다.S6_SERVICES_GRACETIME
(기본값 = 3000): s6
이 종료 시 나머지 종료를 진행하기 전에 /etc/services.d
에 선언된 서비스가 종료될 때까지 기다려야 하는 시간(밀리초)입니다.S6_KILL_GRACETIME
(기본값 = 3000): 모든 프로세스가 TERM 신호를 수신했을 때 종료 절차가 끝날 때 s6
KILL
신호를 보내기 전에 죽기까지 기다려야 하는 시간(밀리초)입니다 . .S6_LOGGING_SCRIPT
(기본값 = "n20 s1000000 T"): 이 환경은 기록할 항목과 기본적으로 모든 줄 앞에 ISO8601을 추가하고 현재 로깅 파일이 1MB에 도달하면 회전하고 최대 20개의 파일로 보관하는 방법을 결정합니다.S6_CMD_ARG0
(기본값 = 설정되지 않음): 이 env var의 값은 docker가 전달한 모든 CMD
인수 앞에 추가됩니다. 기존 이미지를 s6 오버레이로 마이그레이션하고 이를 즉시 교체로 만들려는 경우 이 변수를 사용하십시오. 이 변수를 이전에 사용된 ENTRYPOINT 값으로 설정하면 전환하는 데 도움이 됩니다.S6_CMD_USE_TERMINAL
(기본값 = 0): 출력을 위해 터미널이 필요한 CMD가 있고(일반적으로 docker run -it
사용하여 컨테이너를 실행하는 경우) S6_LOGGING
0이 아닌 값으로 설정한 경우 이 값을 1 로 설정합니다. 이 설정을 사용하면 CMD가 실제로 터미널에 출력됩니다. 단점은 출력이 기록되지 않는다는 것입니다. 기본적으로(이 변수가 0 이거나 설정되지 않은 경우) S6_LOGGING
이 0이 아닐 때 CMD의 stdout 및 stderr이 기록됩니다. 즉, 대화형 터미널에서 실행하더라도 파이프로 이동한다는 의미입니다.S6_FIX_ATTRS_HIDDEN
(기본값 = 0): fix-attrs.d
스크립트가 파일 및 디렉터리를 처리하는 방법을 제어합니다.0
: 숨김 파일 및 디렉터리를 제외합니다.1
: 모든 파일과 디렉터리가 처리됩니다.S6_CMD_WAIT_FOR_SERVICES
(기본값 = 0): 기본적으로 컨테이너가 시작되면 /etc/services.d
의 서비스가 시작되고 실행은 user2
번들 및 CMD 시작으로 진행됩니다(이 중 하나가 정의된 경우). 그러나 S6_CMD_WAIT_FOR_SERVICES
가 0이 아닌 경우 컨테이너 시작 시퀀스는 /etc/services.d
의 서비스가 나머지 시퀀스를 진행하기 전에 준비 될 때까지 기다립니다. 이는 /etc/services.d
의 서비스가 S6에 대한 준비 상태를 알리는 경우에만 중요합니다.S6_CMD_WAIT_FOR_SERVICES_MAXTIME
(Default = 0, 즉 무한) : CMD 실행에 시술하기 전에 서비스가 발생할 수있는 최대 시간 (밀리 초). 잠재적으로 무기한 차단할 수있는 서비스가있는 경우이 변수를 양수 값으로 설정하고 주어진 시간이 지나면 모든 것이 일어나지 않으면 컨테이너가 실패하는 것을 선호합니다. 이 값에는 레거시 컨테이너 초기화 ( /etc/cont-init.d
) 및 서비스 ( /etc/services.d
)를 설정하는 시간도 포함되므로 적절한 값을 계산할 때이를 고려하십시오. 최대 3.1.6.2의 S6-Overlay 버전에서는 기본값이 5000 (5 초)이지만 해결 된 문제보다 원치 않는 컨테이너 고장을 일으켰으므로 이제 기본적으로 시간 초과가 없습니다. S6-Overlay는 오랫동안 대기합니다. 모든 서비스가 제기되는 데 필요합니다.S6_READ_ONLY_ROOT
(Default = 0) : 루트 파일 시스템이 읽기 전용 인 컨테이너에서 실행될 때이 ENV를 1 로 설정하여 init 2 단계로 설정하여 /etc
에서 /run/s6/etc
에 사용자가 제공 한 초기화 스크립트를 복사해야합니다. 자세한 내용은 권한을 변경하려고합니다. 자세한 내용은 읽기 전용 루트 파일 시스템을 참조하십시오.S6_SYNC_DISKS
(default = 0) : 컨테이너를 중지하기 전에 파일 시스템을 동기화해야한다는 INIT 3에 알리려면이 ENV를 1 로 설정하십시오. 참고 : 이것은 호스트의 모든 파일 시스템을 동기화 할 수 있습니다.S6_STAGE2_HOOK
(default = none) :이 변수가 존재하면 그 내용은 서비스가 시작되기 전에 초기 2 단계에서 실행될 쉘 발췌로 해석됩니다. 예를 들어, 컴파일 및 실행 직전에 런타임에 서비스 데이터베이스를 동적으로 패치하는 데 사용할 수 있습니다. 잘못된 가치는 컨테이너가 보안을 실행하지 못하게하거나 보안을 위험에 빠뜨릴 수 있으므로 수행하는 작업을 정확히 아는 경우에만 사용하십시오. 의심스러운 경우이 변수를 정의하지 않도록하십시오.S6_VERBOSITY
(default = 2) : 컨테이너 시작 및 중지 시간시 S6-RC 및 잠재적으로 다른 도구의 표면을 제어합니다. 기본값 2는 일반적으로 장점입니다. 서비스 시작 및 정지 작업을 나열합니다. 이 숫자를 줄임으로써 컨테이너를 더 조용하게 만들 수 있습니다. 1은 경고와 오류 만 인쇄하고 0은 오류 만 인쇄합니다. 이 숫자를 최대 5까지 늘려서 컨테이너를 더욱 장로, 즉 인쇄 추적 및 디버그 정보로 만들 수 있지만 출력은 빠르게 시끄럽게 되며 대부분의 사람들은 이것을 필요로하지 않아야합니다.S6_CMD_RECEIVE_SIGNALS
(default = 0) : 컨테이너로 전송 된 신호를 컨테이너의 PID 1 또는 CMD로 전송 해야하는지 결정합니다. 기본적으로 docker stop
수행하면 용어 신호가 컨테이너의 PID 1로 전송되며, 이는 전체 컨테이너 종료 시퀀스를 트리거 할 것입니다. 그러나 CMD가 있으면 마지막으로 죽을 프로세스 중 하나가됩니다. , 다른 모든 것이 내려와 컨테이너가 종료 될 때만. 이 변수가 1 개 이상인 경우 신호는 PID 1에서 CMD로 전환됩니다. 즉, docker stop
대신 CMD에 SIGTERM을 보내고 CMD가 죽을 때만 컨테이너가 종료 절차를 트리거합니다. Sigerm, Sigquit, Sigint, Sigusr1, Sigusr2, Sigpwr 및 Sigwinch만이 우회됩니다. 다른 신호는 무시되거나 전환 될 수 없으며 PID 1에 의해 반드시 처리 될 수 없습니다.이 옵션을 사용하면 대화식 CMD가 전혀 작동하지 않을 수 있습니다. 다시 말하면, 터미널에서 대화식 CMD를 실행하는 경우 DON입니다. 이 변수를 설정하십시오. 그러나이 경우 이미 CMD를 중지하는 대화식 방법이 있기 때문에 괜찮을 것입니다. 컨테이너에서 실행되는 소프트웨어에 syslog가 필요한 경우 syslogd-overlay-noarch.tar.xz
tarball : 작은 syslogd 에뮬레이션을 제공합니다. 로그는 /var/log/syslogd
의 다양한 하위 디렉토리에서 찾을 수 있습니다. 예를 들어 메시지는 /var/log/syslogd/messages/
directory에서 찾을 수 있으며 /var/log/syslogd/messages/current