Daftar isi
CMD
s6-overlay adalah kumpulan skrip dan utilitas yang mudah dipasang (cukup ekstrak satu atau dua tarball!) yang memungkinkan Anda menggunakan image Docker yang ada saat menggunakan s6 sebagai pid 1 untuk container dan supervisor proses untuk layanan Anda.
Bangun Dockerfile berikut dan cobalah:
# 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
Jika Anda bermigrasi dari s6-overlay versi sebelumnya ( v2 ) ke versi baru ( v3 ), Anda mungkin perlu membuat beberapa perubahan pada layanan atau cara Anda menggunakan s6-overlay agar semuanya berjalan lancar. Dokumen ini mencoba menjelaskan secara akurat cara kerja v3, namun kami memiliki halaman terpisah yang mencantumkan perbedaan utama, dan hal-hal yang mungkin Anda perhatikan. Silakan membacanya jika Anda berada dalam situasi ini!
Proyek ini memiliki tujuan sebagai berikut:
cont-init.d
), finalisasi ( cont-finish.d
) dan layanan mereka sendiri dengan ketergantungan di antara keduanyaPID 1
yang tepats6
dan s6-portable-utils
. Mereka mencakup utilitas praktis dan dapat disusun yang membuat hidup kita jauh lebih mudah.logutil-service
yang menggunakan s6-log
di bawah tenda.USER
Docker, untuk menjalankan seluruh pohon proses Anda sebagai pengguna tertentu. Tidak kompatibel dengan semua fitur, detail di bagian catatan. Salah satu mantra Docker yang sering diulang adalah "satu proses per kontainer", tapi kami tidak setuju. Tidak ada yang buruk tentang menjalankan banyak proses dalam satu wadah. Kebijakan kami adalah "satu hal per penampung" yang lebih abstrak - sebuah penampung harus melakukan satu hal, seperti "menjalankan layanan obrolan" atau "menjalankan gitlab". Ini mungkin melibatkan banyak proses, dan itu tidak masalah.
Alasan lain pembuat image menghindari pengawas proses adalah karena mereka percaya bahwa pengawas proses harus memulai ulang layanan yang gagal, artinya container Docker tidak akan pernah mati.
Hal ini secara efektif merusak ekosistem Docker - sebagian besar image menjalankan satu proses yang akan keluar jika terjadi kesalahan. Dengan keluar karena kesalahan, Anda mengizinkan administrator sistem untuk menangani kegagalan sesuai keinginannya. Jika gambar Anda tidak pernah keluar, Anda sekarang memerlukan beberapa metode alternatif untuk pemulihan kesalahan dan pemberitahuan kegagalan.
Kebijakan kami adalah jika "sesuatu" gagal, maka containernya juga akan gagal. Kami melakukan ini dengan menentukan proses mana yang dapat dimulai ulang, dan proses mana yang harus mematikan container. Misalnya, jika cron
atau syslog
gagal, container Anda kemungkinan besar dapat memulai ulang tanpa efek buruk apa pun, namun jika ejabberd
gagal, container harus keluar sehingga administrator sistem dapat mengambil tindakan.
Interpretasi kami tentang "The Docker Way" adalah sebagai berikut:
dan sistem init kami dirancang untuk melakukan hal itu. Gambar Anda akan berperilaku seperti gambar Docker lainnya dan cocok dengan ekosistem gambar yang ada.
Lihat "Menulis skrip penyelesaian opsional" di bawah bagian Penggunaan untuk detail tentang menghentikan "sesuatu".
Overlay init kami disesuaikan dengan benar agar dapat berjalan dengan tepat di lingkungan dalam container. Bagian ini menjelaskan secara singkat cara kerja tahapan tetapi jika Anda ingin mengetahui cara kerja sistem init yang lengkap, Anda dapat membaca artikel ini: Cara menjalankan s6-svscan sebagai proses 1
/etc/cont-init.d
./etc/s6-overlay/s6-rc.d
, dependensi berikut/etc/services.d
) ke direktori sementara dan minta s6 memulai (dan mengawasinya)./etc/cont-finish.d
.TERM
ke semua proses yang tersisa. Lagipula tidak boleh ada proses yang tersisa.KILL
. Kemudian wadahnya keluar. s6-overlay hadir sebagai sekumpulan tarball yang dapat Anda ekstrak ke gambar Anda. Tarball yang Anda butuhkan adalah fungsi dari gambar yang Anda gunakan; kebanyakan orang membutuhkan dua yang pertama, dan yang lainnya adalah tambahan yang dapat Anda gunakan sesuai keinginan Anda.
s6-overlay-noarch.tar.xz
: tarball ini berisi skrip yang mengimplementasikan overlay. Kami menyebutnya "noarch" karena tidak bergantung pada arsitektur: hanya berisi skrip dan file teks lainnya. Setiap orang yang ingin menjalankan s6-overlay perlu mengekstrak tarball ini.s6-overlay-x86_64.tar.xz
: ganti x86_64
dengan arsitektur sistem Anda. Tarball ini berisi semua biner yang diperlukan dari ekosistem s6, semuanya terhubung secara statis dan tidak mengganggu biner gambar Anda. Kecuali Anda tahu pasti bahwa gambar Anda sudah dilengkapi dengan semua paket yang menyediakan biner yang digunakan dalam overlay, Anda perlu mengekstrak tarball ini.s6-overlay-symlinks-noarch.tar.xz
: tarball ini berisi symlink ke skrip s6-overlay sehingga dapat diakses melalui /usr/bin
. Biasanya tidak diperlukan, semua skrip dapat diakses melalui variabel lingkungan PATH, tetapi jika Anda memiliki skrip pengguna lama yang berisi shebang seperti #!/usr/bin/with-contenv
, memasang symlink ini akan membuatnya berfungsi.s6-overlay-symlinks-arch.tar.xz
: tarball ini berisi symlink ke biner dari ekosistem s6 yang disediakan oleh tarball kedua, agar dapat diakses melalui /usr/bin
. Biasanya tidak diperlukan, tetapi jika Anda memiliki skrip pengguna lama yang berisi shebang seperti #!/usr/bin/execlineb
, menginstal symlink ini akan membuatnya berfungsi.syslogd-overlay-noarch.tar.xz
: tarball ini berisi definisi untuk layanan syslogd
. Jika Anda menjalankan daemon yang tidak dapat masuk ke stderr untuk memanfaatkan infrastruktur logging s6, tetapi melakukan hardcode menggunakan mekanisme syslog()
yang lama, Anda dapat mengekstrak tarball ini, dan kontainer Anda akan menjalankan emulasi ringan daemon syslogd
, jadi log syslog Anda akan ditangkap dan disimpan ke disk.Untuk menginstal tarball tersebut, tambahkan baris ke Dockerfile Anda yang sesuai dengan fungsionalitas yang ingin Anda instal. Misalnya, kebanyakan orang akan menggunakan yang berikut ini:
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
Pastikan untuk mempertahankan izin file saat mengekstraksi (yaitu menggunakan opsi -p
ke tar
.)
Proyek ini didistribusikan sebagai sekumpulan file .tar.xz standar, yang Anda ekstrak di root gambar Anda. (Anda memerlukan paket xz-utils agar tar
dapat memahami file .tar.xz
; paket ini tersedia di setiap distribusi, namun tidak selalu dalam gambar kontainer default, jadi Anda mungkin perlu apt install xz-utils
atau apk add xz
, atau setara, sebelum Anda dapat memperluas arsipnya.)
Setelah itu, atur ENTRYPOINT
Anda ke /init
.
Saat ini, kami merekomendasikan penggunaan direktif ADD
Docker daripada menjalankan wget
atau curl
dalam direktif RUN
- Docker dapat menangani URL https saat Anda menggunakan ADD
, sedangkan gambar dasar Anda mungkin tidak dapat menggunakan https, atau bahkan mungkin tidak memilikinya. wget
atau curl
diinstal sama sekali.
Dari sana, Anda memiliki beberapa opsi:
CMD
gambar Anda.CMD
Menggunakan CMD
adalah cara mudah untuk memanfaatkan overlay. CMD
Anda dapat diberikan pada waktu pembuatan di Dockerfile, atau pada waktu proses di baris perintah, apa pun itu baik-baik saja. Ini akan dijalankan sebagai proses normal di lingkungan yang diatur oleh s6; ketika gagal atau keluar, wadah akan mati dengan bersih dan keluar. Anda dapat menjalankan program interaktif dengan cara ini: hanya CMD yang akan menerima perintah interaktif Anda, proses dukungan tidak akan terpengaruh.
Misalnya:
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 $
Cara lain untuk menggunakan container dengan s6-overlay adalah dengan membuat layanan Anda diawasi. Anda dapat mengawasi sejumlah layanan; biasanya itu hanya layanan dukungan untuk daemon utama yang Anda jalankan sebagai CMD, tetapi jika itu yang Anda inginkan, tidak ada yang menghalangi Anda untuk memiliki CMD kosong dan menjalankan daemon utama Anda sebagai layanan yang diawasi juga. Dalam hal ini, daemon akan di-restart oleh s6 setiap kali daemon keluar; container hanya akan berhenti ketika Anda memerintahkannya untuk melakukannya, baik melalui perintah docker stop
, atau dari dalam container dengan perintah /run/s6/basedir/bin/halt
.
Ada dua cara untuk membuat layanan yang diawasi. Cara lama yang masih didukung adalah dengan membuat direktori layanan "s6 murni". Buat direktori dengan nama layanan Anda di /etc/services.d
dan masukkan file run
yang dapat dieksekusi ke dalamnya; ini adalah file tempat Anda akan meletakkan proses eksekusi yang berumur panjang. Untuk detail pengawasan direktori layanan, dan bagaimana Anda dapat mengonfigurasi cara s6 menangani daemon Anda, Anda dapat melihat dokumentasi servicedir. Contoh sederhananya akan terlihat seperti ini:
/etc/services.d/myapp/run
:
#!/command/execlineb -P
nginx -g "daemon off;"
Cara barunya adalah dengan membuat direktori definisi sumber s6-rc di direktori /etc/s6-overlay/s6-rc.d
, dan menambahkan nama direktori tersebut ke bundel user
, yaitu membuat file kosong dengan nama yang sama di direktori /etc/s6-overlay/s6-rc.d/user/contents.d
. Format direktori definisi sumber dijelaskan di halaman ini. Perhatikan bahwa Anda dapat mendefinisikan longruns , yaitu daemon yang akan diawasi oleh s6 seperti halnya dengan metode /etc/services.d
, tetapi juga oneshots , yaitu program yang akan dijalankan sekali dan keluar. Layanan utama Anda mungkin bersifat jangka panjang , bukan oneshot : Anda mungkin memerlukan daemon untuk bertahan.
Keuntungan dari format baru ini adalah memungkinkan Anda untuk menentukan ketergantungan antar layanan: jika B bergantung pada A , maka A akan memulai terlebih dahulu, kemudian B akan memulai ketika A siap, dan ketika kontainer disuruh keluar, B akan berhenti pertama, lalu A. Jika Anda memiliki arsitektur yang kompleks di mana berbagai proses bergantung satu sama lain, atau jika Anda harus menggabungkan oneshot dan longrun dalam urutan yang tepat, ini mungkin cocok untuk Anda.
Contoh di atas dapat ditulis ulang seperti ini:
/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
: file kosong. (Ini menambahkan myapp
ke rangkaian layanan yang s6-rc akan mulai saat boot container.)
/etc/s6-overlay/s6-rc.d/myapp/dependencies.d/base
: file kosong. (Ini memberitahu s6-rc untuk hanya memulai myapp
ketika semua layanan dasar sudah siap: ini mencegah kondisi balapan.)
Kami mendorong Anda untuk beralih ke format baru, tetapi jika Anda tidak memerlukan manfaatnya, Anda dapat tetap menggunakan direktori layanan reguler di /etc/services.d
, ini juga akan berfungsi dengan baik.
Jika Anda menjalankan layanan utama sebagai CMD, Anda tidak perlu melakukan apa pun: saat CMD Anda keluar, atau saat Anda menjalankan docker stop
, container akan keluar secara alami dengan kode keluar yang sama dengan layanan Anda. (Namun, perlu diketahui bahwa dalam kasus docker stop
, layanan Anda akan mendapatkan SIGTERM, dalam hal ini kode keluar akan sepenuhnya bergantung pada cara layanan Anda menanganinya - layanan Anda dapat menjebaknya dan keluar dari 0, menjebaknya, dan keluar dari sesuatu yang lain , atau tidak menjebaknya dan membiarkan shell mengeluarkan kodenya sendiri - biasanya 130.)
Namun, jika Anda menjalankan layanan utama sebagai layanan yang diawasi, segalanya akan berbeda, dan Anda perlu memberi tahu container kode apa yang harus digunakan untuk keluar saat Anda mengirimkan perintah docker stop
. Untuk melakukan itu, Anda perlu menulis skrip finish
:
/etc/services.d
, Anda memerlukan skrip /etc/services.d/myapp/finish
yang dapat dieksekusi./etc/s6-overlay/s6-rc.d/myapp/finish
yang berisi skrip Anda (file tersebut mungkin dapat dieksekusi atau tidak). Skrip finish
ini akan dijalankan ketika layanan Anda keluar, dan akan mengambil dua argumen:
Di skrip finish
, Anda perlu menulis kode keluar container yang Anda inginkan ke file /run/s6-linux-init-container-results/exitcode
- dan selesai.
Misalnya, skrip finish
untuk layanan myapp
di atas bisa seperti ini:
#! /bin/sh
if test " $1 " -eq 256 ; then
e= $(( 128 + $2 ))
else
e= " $1 "
fi
echo " $e " > /run/s6-linux-init-container-results/exitcode
Saat Anda mengirim perintah docker stop
ke container Anda, layanan myapp
akan dimatikan dan skrip ini akan dijalankan; ia akan menulis kode keluar myapp
(jika myapp
menangkap sinyal TERM) atau 130 (jika myapp
tidak menangkap sinyal TERM) ke file khusus /run/s6-linux-init-container-results/exitcode
, yang akan dibaca oleh s6-overlay di akhir prosedur penutupan kontainer, dan kontainer Anda akan keluar dengan nilai tersebut.
Bagian ini menjelaskan fungsionalitas dari versi s6-overlay yang sebelum v3. fix-attrs masih didukung di v3, namun tidak digunakan lagi karena beberapa alasan: salah satunya adalah bahwa umumnya tidak baik untuk mengubah kepemilikan secara dinamis jika hal ini dapat dilakukan secara statis. Alasan lainnya adalah karena ini tidak berfungsi dengan kontainer USER. Daripada memperbaiki attrs, kami sekarang menyarankan Anda untuk mengurus kepemilikan dan izin pada host mount secara offline, sebelum menjalankan container . Ini harus dilakukan di Dockerfile Anda, ketika Anda memiliki semua informasi yang diperlukan.
Meskipun demikian, inilah yang kami tulis untuk versi sebelumnya dan masih berlaku hingga saat ini (tapi harap berhenti bergantung pada versi tersebut):
Terkadang menarik untuk memperbaiki kepemilikan & izin sebelum melanjutkan karena, misalnya, Anda telah memasang/memetakan folder host di dalam wadah Anda. Hamparan kami menyediakan cara untuk mengatasi masalah ini menggunakan file di /etc/fix-attrs.d
. Ini adalah format pola yang diikuti oleh file fix-attrs:
path recurse account fmode dmode
path
: Jalur file atau direktori.recurse
: (Setel ke true
atau false
) Jika sebuah folder ditemukan, lakukan recurse melalui semua file & folder yang berisi di dalamnya.account
: Akun target. Dimungkinkan untuk menggunakan fallback uid:gid
secara default jika akun tidak ditemukan. Misalnya, nobody,32768:32768
akan mencoba menggunakan akun nobody
terlebih dahulu, lalu kembali ke uid 32768
. Jika, misalnya, akun daemon
adalah UID=2
dan GID=2
, berikut adalah nilai yang mungkin untuk bidang 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
: Mode file target. Misalnya, 0644
.dmode
: Mode direktori/folder target. Misalnya, 0755
.Di sini Anda memiliki beberapa contoh kerja:
/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
Inilah cara lama untuk melakukannya:
Setelah memperbaiki atribut (melalui /etc/fix-attrs.d/
) dan sebelum memulai layanan yang disediakan pengguna (melalui s6-rc atau /etc/services.d
) overlay kami akan menjalankan semua skrip yang ditemukan di /etc/cont-init.d
, misalnya:
/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
Cara ini masih didukung. Namun, sekarang ada cara yang lebih umum dan efisien untuk melakukannya: menulis tugas inisialisasi dan finalisasi oneshot Anda sebagai layanan s6-rc, dengan menambahkan direktori definisi layanan di /etc/s6-overlay/s6-rc.d
, menjadikannya bagian dari bundel user
(sehingga mereka benar-benar dimulai ketika kontainer melakukan booting), dan membuatnya bergantung pada bundel base
(jadi mereka hanya dimulai setelah base
).
Semua informasi tentang s6-rc dapat ditemukan di sini.
Saat kontainer dimulai, operasi dilakukan dalam urutan berikut:
/etc/fix-attrs.d
./etc/cont-init.d
dijalankan secara berurutan.user
dimulai oleh s6-rc, dalam urutan yang ditentukan oleh dependensi. Layanan dapat berupa oneshots (tugas inisialisasi) atau longruns (daemon yang akan berjalan sepanjang masa pakai container). Jika layanan bergantung pada base
, layanan dijamin akan dimulai pada saat ini dan bukan lebih awal; jika tidak, mereka mungkin sudah dimulai lebih awal, yang dapat menyebabkan kondisi balapan - jadi disarankan untuk selalu membuatnya bergantung pada base
./etc/services.d
dimulai.user2
dengan ketergantungan yang benar dimulai. (Kebanyakan orang tidak perlu menggunakan ini; jika Anda tidak yakin, tetap gunakan bundel user
.)Ketika kontainer dihentikan, karena admin mengirimkan perintah stop atau karena CMD keluar, operasi dilakukan dalam urutan terbalik:
user2
dengan ketergantungan yang benar dihentikan./etc/services.d
dihentikan.down
di direktori definisi sumber dijalankan; begitulah cara s6-rc dapat melakukan tugas finalisasi./etc/cont-finish.d
dijalankan secara berurutan. Inti dari bundel user2
adalah untuk memungkinkan layanan pengguna yang dideklarasikan di dalamnya dimulai setelah yang /etc/services.d
; tetapi untuk melakukannya, setiap layanan di user2
perlu mendeklarasikan ketergantungan pada legacy-services
. Dengan kata lain, agar foobar
layanan terlambat dimulai, Anda perlu:
/etc/s6-overlay/s6-rc.d/foobar
seperti layanan s6-rc lainnya./etc/s6-overlay/s6-rc.d/foobar/dependencies.d/legacy-services
/etc/s6-overlay/s6-rc.d/user2/contents.d/foobar
. Itu akan memastikan bahwa foobar
akan dimulai setelah semua yang ada di /etc/services.d
.
Secara default, layanan yang dibuat di /etc/services.d
akan dimulai ulang secara otomatis. Jika suatu layanan membuat containernya down, Anda mungkin harus menjalankannya sebagai CMD; namun jika Anda lebih suka menjalankannya sebagai layanan yang diawasi, Anda harus menulis skrip finish
, yang akan dijalankan saat layanan tidak aktif; untuk menghentikan container, perintah /run/s6/basedir/bin/halt
harus dijalankan. Berikut ini contoh skrip penyelesaian:
/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
Baris pertama skrip menulis 0
ke file /run/s6-linux-init-container-results/exitcode
. Baris kedua menghentikan wadah. Ketika Anda menghentikan container melalui perintah /run/s6/basedir/bin/halt
yang dijalankan dari dalam container, /run/s6-linux-init-container-results/exitcode
dibaca dan isinya digunakan sebagai kode keluar untuk perintah docker run
yang meluncurkan container. Jika file tidak ada, atau jika kontainer dihentikan karena docker stop
atau alasan lain, kode keluar tersebut defaultnya adalah 0.
Dimungkinkan untuk melakukan operasi lebih lanjut dalam skrip akhir. Misalnya, inilah skrip yang hanya mematikan layanan ketika keluar dari angka bukan nol:
/etc/services.d/myapp/finish
:
#!/command/execlineb -S1
if { eltest ${1} -ne 0 -a ${1} -ne 256 }
/run/s6/basedir/bin/halt
Perhatikan bahwa secara umum, skrip penyelesaian hanya boleh digunakan untuk pembersihan lokal setelah daemon mati. Jika suatu layanan sangat penting sehingga container harus dihentikan ketika mati, kami sangat menyarankan untuk menjalankannya sebagai CMD.
Setiap layanan dapat memiliki logger khusus. Logger adalah layanan s6 yang secara otomatis membaca dari stdout layanan Anda, dan mencatat data ke file yang diputar secara otomatis di tempat yang Anda inginkan. Perhatikan bahwa daemon biasanya masuk ke stderr, bukan stdout, jadi Anda mungkin harus memulai skrip run layanan Anda dengan exec 2>&1
di shell, atau dengan fdmove -c 2 1
di execline, untuk menangkap stderr .
s6-overlay menyediakan utilitas bernama logutil-service
yang merupakan pembungkus program s6-log
. Pembantu ini melakukan hal berikut:
S6_LOGGING_SCRIPT
nobody
(defaultnya adalah 65534:65534
jika tidak ada) s6-log kemudian akan berjalan selamanya, membaca data dari layanan Anda dan menulisnya ke direktori yang Anda tentukan ke logutil-service
.
Harap dicatat:
s6-setuidgid
nobody
nobody
. Anda dapat membuat folder log dalam skrip cont-init.d
, atau sebagai s6-rc oneshots. Berikut adalah contoh layanan log myapp
yang diterapkan dengan cara lama:
/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
Dan ini layanan yang sama, myapp, diimplementasikan di s6-rc.
/etc/s6-overlay/s6-rc.d/myapp-log-prepare/dependencies.d/base
: file kosong
/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
(Awal dari bagian terperinci.)
Jadi, file up
dan down
itu istimewa: itu bukan skrip shell, tetapi baris perintah tunggal yang ditafsirkan oleh execlineb. Anda tidak perlu khawatir tentang execline; Anda hanya perlu mengingat bahwa file up
berisi satu baris perintah. Jadi jika Anda memerlukan skrip dengan beberapa instruksi, berikut cara melakukannya:
up
. Inilah cara Anda biasanya melanjutkan up
file untuk myapp-log-prepare
:
/etc/s6-overlay/s6-rc.d/myapp-log-prepare/up
:
/etc/s6-overlay/scripts/myapp-log-prepare
/etc/s6-overlay/scripts/myapp-log-prepare
: (harus dapat dieksekusi)
#! /bin/sh -e
mkdir -p /var/log/myapp
chown nobody:nogroup /var/log/myapp
chmod 02755 /var/log/myapp
Lokasi skrip sebenarnya bisa berubah-ubah, hanya perlu cocok dengan apa yang Anda tulis di file up
.
Tapi di sini, kebetulan skripnya cukup sederhana sehingga bisa muat seluruhnya di file up
tanpa membuatnya terlalu rumit atau terlalu sulit untuk dipahami. Jadi, kami memilih untuk menyertakannya sebagai contoh untuk menunjukkan bahwa masih banyak lagi yang dapat Anda lakukan dengan up
, jika Anda menginginkannya. Anda dapat membaca dokumentasi lengkap untuk bahasa execline di sini.
(Akhir dari bagian detail, klik lagi segitiga di atas untuk menciutkannya.)
/etc/s6-overlay/s6-rc.d/myapp/dependencies.d/base
: file kosong
/etc/s6-overlay/s6-rc.d/myapp-log/dependencies.d/myapp-log-prepare
: file kosong
/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
: file kosong
Itu banyak sekali filenya! Ringkasan dari arti semua itu adalah:
myapp | myapp-log
Pipeline myapp | myapp-log
diberi nama, myapp-pipeline
, dan nama ini dideklarasikan sebagai bagian dari bundel user
, sehingga akan dimulai saat container dimulai.myapp-log-prepare
, myapp-log
dan myapp
semuanya bergantung pada paket base
, yang berarti mereka hanya akan dimulai ketika sistem benar-benar siap untuk memulainya. Ini benar-benar menyelesaikan hal yang sama seperti metode /etc/cont-init.d
plus /etc/services.d
, tetapi jauh lebih bersih di bawahnya, dan dapat menangani grafik ketergantungan yang jauh lebih kompleks, jadi kapan pun Anda mendapat kesempatan, kami sarankan Anda membiasakan diri dengan cara s6-rc mendeklarasikan layanan dan logger Anda. Sintaks lengkap direktori definisi layanan, termasuk mendeklarasikan apakah layanan Anda jangka panjang atau oneshot, mendeklarasikan pipeline, menambahkan batas waktu khusus layanan jika Anda memerlukannya, dll., dapat ditemukan di sini.
Saat menjalankan suatu layanan, tidak peduli apakah itu layanan atau logger, praktik yang baik adalah menghilangkan hak istimewa sebelum menjalankannya. s6
sudah menyertakan utilitas untuk melakukan hal-hal seperti ini:
Secara execline
:
#!/command/execlineb -P
s6-setuidgid daemon
myservice
Di sh
:
#! /bin/sh
exec s6-setuidgid daemon myservice
Jika Anda ingin tahu lebih banyak tentang utilitas ini, silakan lihat: s6-setuidgid
, s6-envuidgid
, dan s6-applyuidgid
.
Jika Anda ingin skrip khusus Anda memiliki lingkungan kontainer yang tersedia: Anda dapat menggunakan pembantu with-contenv
, yang akan memasukkan semuanya ke dalam lingkungan eksekusi Anda, misalnya:
/etc/cont-init.d/01-contenv-example
:
#! /command/with-contenv sh
env
Skrip ini akan menampilkan konten lingkungan kontainer Anda.
Versi terbaru Docker memungkinkan menjalankan container dengan sistem file root read-only. Jika penampung Anda berada dalam kasus seperti itu, Anda harus menyetel S6_READ_ONLY_ROOT=1
untuk memberi tahu s6-overlay bahwa penampung tersebut tidak boleh mencoba menulis ke area tertentu - sebagai gantinya, ia akan melakukan penyalinan ke tmpfs yang dipasang di /run
.
Perhatikan bahwa s6-overlay mengasumsikan bahwa:
/run
ada dan dapat ditulis. Jika tidak, ia akan mencoba memasang tmpfs di sana./var/run
adalah tautan simbolik ke /run
, untuk kompatibilitas dengan versi sebelumnya. Jika tidak, maka akan terjadi demikian. Secara umum pengaturan buruh pelabuhan default Anda seharusnya sudah menyediakan tmpfs yang sesuai /run
.
Entah bagaimana, dimungkinkan untuk mengubah perilaku s6-overlay dengan menyediakan serangkaian variabel lingkungan yang sudah ditentukan sebelumnya ke konteks eksekusi:
PATH
(default = /command:/usr/bin:/bin
): ini adalah PATH default yang dimiliki semua layanan dalam container, termasuk CMD. Setel variabel ini jika Anda memiliki banyak layanan yang bergantung pada binari yang disimpan di direktori lain, misalnya /usr/sbin
. Perhatikan bahwa /command
, /usr/bin
dan /bin
akan selalu ditambahkan ke jalur tersebut jika belum ada di jalur yang Anda berikan.S6_KEEP_ENV
(default = 0): jika disetel, maka lingkungan tidak disetel ulang dan seluruh pohon pengawasan melihat kumpulan env vars asli. Ini beralih with-contenv
menjadi tidak.S6_LOGGING
(standar = 0):0
: Menampilkan semuanya ke stdout/stderr.1
: Menggunakan logger catch-all
internal dan menyimpan semua yang ada di dalamnya, terletak di /var/log/s6-uncaught-logs
. Apa pun yang dijalankan sebagai CMD
masih ditampilkan ke stdout/stderr.2
: Menggunakan pencatat catch-all
internal dan menyimpan semua yang ada di dalamnya, termasuk keluaran CMD
. Sama sekali tidak ada yang ditulis ke stdout/stderr.S6_CATCHALL_USER
(default = root): jika disetel, dan jika S6_LOGGING
adalah 1 atau 2, maka catch-all logger dijalankan sebagai pengguna ini, yang harus ditentukan dalam /etc/passwd
gambar Anda. Setiap pemisahan hak istimewa sedikit membantu keamanan.S6_BEHAVIOUR_IF_STAGE2_FAILS
(default = 0): menentukan apa yang harus dilakukan kontainer jika salah satu skrip layanan gagal. Ini termasuk:fix-attrs
/etc/cont-init.d
atau gaya baru s6-rc oneshot gagal/etc/services.d
gaya lama atau s6-rc longrun gaya baru yang ditandai sebagai pemberitahuan kesiapan yang diharapkan, dan gagal siap dalam waktu yang ditentukan (lihat S6_CMD_WAIT_FOR_SERVICES_MAXTIME
di bawah). Nilai yang valid untuk S6_BEHAVIOUR_IF_STAGE2_FAILS
adalah sebagai berikut:0
: Lanjutkan secara diam-diam meskipun skrip gagal.1
: Lanjutkan tetapi peringatkan dengan pesan kesalahan yang mengganggu.2
: Hentikan wadahnya.S6_KILL_FINISH_MAXTIME
(default = 5000): Berapa lama (dalam milidetik) sistem harus menunggu, pada waktu shutdown, agar skrip di /etc/cont-finish.d
selesai secara alami. Setelah durasi tersebut, skrip akan dikirimkan SIGKILL. Ingatlah bahwa skrip di /etc/cont.finish.d
dijalankan secara berurutan, dan urutan pematian berpotensi menunggu S6_KILL_FINISH_MAXTIME
milidetik untuk setiap skrip.S6_SERVICES_READYTIME
(default = 50): Dengan layanan yang dideklarasikan dalam /etc/services.d
, terdapat kondisi perlombaan yang tidak dapat dihindari antara saat layanan dimulai dan saat layanan dapat diuji kesiapannya. Untuk menghindari perlombaan itu, kami tidur sebentar, secara default 50 milidetik, sebelum menguji kesiapan. Jika mesin Anda lambat atau sangat sibuk, Anda mungkin mendapatkan kesalahan seperti s6-svwait: fatal: unable to s6_svstatus_read: No such file or directory
. Dalam hal ini, Anda harus menambah waktu tidur, dengan mendeklarasikannya (dalam milidetik) dalam variabel S6_SERVICES_READYTIME
. Perhatikan bahwa ini hanya menyangkut /etc/services.d
; s6-rc kebal terhadap kondisi balapan.S6_SERVICES_GRACETIME
(default = 3000): Berapa lama (dalam milidetik) s6
harus menunggu, pada waktu penghentian, hingga layanan yang dideklarasikan di /etc/services.d
mati sebelum melanjutkan proses pematian selanjutnya.S6_KILL_GRACETIME
(default = 3000): Berapa lama (dalam milidetik) s6
harus menunggu, di akhir prosedur shutdown ketika semua proses telah menerima sinyal TERM, agar proses tersebut mati sebelum mengirimkan sinyal KILL
untuk memastikan proses tersebut mati .S6_LOGGING_SCRIPT
(default = "n20 s1000000 T"): Env ini memutuskan apa yang akan dicatat dan bagaimana, secara default setiap baris akan diawali dengan ISO8601, diputar ketika file logging saat ini mencapai 1mb dan diarsipkan, paling banyak, dengan 20 file.S6_CMD_ARG0
(default = not set): Nilai env var ini akan ditambahkan ke argumen CMD
apa pun yang diteruskan oleh buruh pelabuhan. Gunakan jika Anda memigrasikan gambar yang sudah ada ke s6-overlay dan ingin menjadikannya pengganti drop-in: mengatur variabel ini ke nilai ENTRYPOINT yang digunakan sebelumnya akan membantu Anda melakukan transisi.S6_CMD_USE_TERMINAL
(default = 0): Setel nilai ini ke 1 jika Anda memiliki CMD yang memerlukan terminal untuk outputnya (biasanya saat Anda menjalankan container dengan docker run -it
), dan Anda telah menyetel S6_LOGGING
ke nilai bukan nol. Pengaturan ini akan membuat CMD Anda benar-benar dikeluarkan ke terminal Anda; kekurangannya adalah outputnya tidak akan dicatat. Secara default (jika variabel ini 0 atau tidak disetel), stdout dan stderr CMD Anda dicatat ketika S6_LOGGING
bukan nol, yang berarti keduanya masuk ke pipa meskipun Anda menjalankannya di terminal interaktif.S6_FIX_ATTRS_HIDDEN
(default = 0): Mengontrol cara skrip fix-attrs.d
memproses file dan direktori.0
: File dan direktori tersembunyi tidak termasuk.1
: Semua file dan direktori diproses.S6_CMD_WAIT_FOR_SERVICES
(default = 0): Secara default ketika kontainer dimulai, layanan di /etc/services.d
akan dimulai dan eksekusi akan dilanjutkan untuk memulai bundel user2
dan CMD, jika salah satu dari ini ditentukan. Jika S6_CMD_WAIT_FOR_SERVICES
adalah bukan nol, bagaimanapun, urutan awal wadah akan menunggu sampai layanan di /etc/services.d
siap sebelum melanjutkan dengan sisa urutan. Perhatikan bahwa ini hanya penting jika layanan di /etc/services.d
memberi tahu kesiapan mereka kepada S6.S6_CMD_WAIT_FOR_SERVICES_MAXTIME
(default = 0, yaitu Infinite): Waktu maksimum (dalam milidetik) Layanan dapat dibawa untuk dibawa sebelum proseding untuk mengeksekusi CMD. Tetapkan variabel ini ke nilai positif jika Anda memiliki layanan yang berpotensi memblokir tanpa batas waktu dan Anda lebih suka wadah gagal jika tidak semuanya naik setelah waktu tertentu. Perhatikan bahwa nilai ini juga mencakup penyiapan waktu inisialisasi wadah warisan ( /etc/cont-init.d
) dan layanan ( /etc/services.d
), jadi pertimbangkan itu saat menghitung nilai yang sesuai. Dalam versi S6-overlay hingga 3.1.6.2, standarnya adalah 5000 (lima detik), tetapi itu menyebabkan lebih banyak kegagalan kontainer yang tidak diinginkan daripada masalah yang diselesaikan, jadi sekarang tidak ada batas waktu secara default: S6-overlay akan menunggu selama ada selama ada perlu semua layanan diangkat.S6_READ_ONLY_ROOT
(default = 0): Saat berjalan dalam wadah yang sistem file root-nya hanya baca, atur env ini ke 1 untuk menginformasikan init stadium 2 bahwa mereka harus menyalin skrip inisialisasi yang disediakan pengguna dari /etc
ke /run/s6/etc
sebelumnya Ia mencoba untuk mengubah izin, dll. Lihat sistem file root hanya baca untuk informasi lebih lanjut.S6_SYNC_DISKS
(default = 0): Setel env ini ke 1 untuk menginformasikan init stadium 3 bahwa ia harus mencoba menyinkronkan sistem file sebelum menghentikan wadah. Catatan: Ini kemungkinan akan menyinkronkan semua sistem file pada host.S6_STAGE2_HOOK
(default = none): Jika variabel ini ada, isinya akan ditafsirkan sebagai kutipan shell yang akan dijalankan pada tahap awal 2, sebelum layanan dimulai. Ini dapat digunakan, misalnya, untuk secara dinamis menambal database layanan pada run-time tepat sebelum dikompilasi dan dijalankan. Nilai yang salah dapat mencegah wadah Anda menjalankan atau membahayakan keamanan Anda, jadi hanya gunakan ini jika Anda tahu persis apa yang Anda lakukan. Jika ragu, biarkan variabel ini tidak terdefinisi.S6_VERBOSITY
(default = 2): Mengontrol verbositas S6-RC, dan berpotensi alat lain, pada wadah mulai dan berhenti waktu. Default, 2, biasanya bertele -tele: ia akan mencantumkan operasi Layanan Mulai dan Menghentikan. Anda dapat membuat wadah lebih tenang dengan mengurangi nomor ini: 1 hanya akan mencetak peringatan dan kesalahan, dan 0 hanya akan mencetak kesalahan. Anda juga dapat membuat wadah lebih banyak verbose, yaitu mencetak informasi dan debug, dengan meningkatkan angka ini hingga 5, tetapi output akan dengan cepat menjadi sangat bising, dan kebanyakan orang tidak perlu membutuhkan ini.S6_CMD_RECEIVE_SIGNALS
(default = 0): Memutuskan apakah sinyal yang dikirim ke wadah harus dikirim ke PID 1 kontainer atau ke CMD. Secara default, ketika Anda melakukan misalnya docker stop
, sinyal istilah akan dikirim ke PID 1 wadah, yang akan memicu urutan shutdown kontainer penuh - tetapi jika ada CMD, itu akan menjadi salah satu proses terakhir yang akan dibunuh , hanya ketika yang lainnya turun dan wadah akan keluar. Jika variabel ini adalah 1 atau lebih, sinyal dialihkan dari PID 1 ke CMD, yang berarti bahwa docker stop
akan mengirim sigterm ke CMD sebagai gantinya, dan wadah hanya akan memicu prosedur shutdown ketika CMD mati. Perhatikan bahwa hanya sigterm, sigquit, sigint, sigusr1, sigusr2, sigpwr dan sigwinch dialihkan; Sinyal lain diabaikan atau tidak dapat dialihkan dan harus ditangani oleh PID 1. Perlu diketahui bahwa menggunakan opsi ini dapat mencegah CMD interaktif bekerja sama sekali - dengan kata lain, jika Anda menjalankan CMD interaktif di terminal, Don 't mengatur variabel ini; Tapi itu seharusnya baik karena dalam hal ini Anda sudah memiliki cara interaktif untuk menghentikan CMD Anda. Jika perangkat lunak yang berjalan di dalam wadah Anda memerlukan syslog, ekstrak tarball syslogd-overlay-noarch.tar.xz
: itu akan memberi Anda emulasi syslogd kecil. Log akan ditemukan di bawah berbagai subdirektori /var/log/syslogd
, misalnya pesan akan ditemukan di /var/log/syslogd/messages/
direktori, log terbaru yang tersedia di /var/log/syslogd/messages/current