2013-12-16 19 views
15

tôi có một kịch bản điểm vào trong một container Docker trông giống như sau:bẫy tín hiệu từ "dừng Docker" trong bash

#!/bin/bash 

echo starting up 

function shut_down() { 
    echo shutting down 

    pid=$(ps -e | grep myapp | awk '{print $1}') 
    kill -SIGTERM $pid 
    exit 
} 

trap "shut_down" SIGKILL SIGTERM SIGHUP SIGINT EXIT 

/opt/myapp 

tôi không thể tìm ra cách để bẫy các tín hiệu được gửi bằng chạy docker stop trên vùng chứa. Khi chạy một cách tương tác, một ctrl+c sẽ kích hoạt nó như mong đợi, nhưng một lệnh docker stop chỉ chờ đợi cho thời gian chờ 10 giây, và thoát ra mà không bao giờ bước vào shut_down chức năng

Làm thế nào tôi có thể bẫy tín hiệu gửi bởi docker stop trong bash để làm một số dọn dẹp?

Trả lời

8

Có một cái nhìn tại this, có thể truyền cảm hứng cho :-)

UPDATE:

@ nick-humrich ở đây nó là là bản sao lamer tôi & qua (tín dụng đi vào tác giả ban đầu https://github.com/lgierth)

#!/bin/bash 

function ensure_started_container { 
    exists=`docker ps -q | grep $1` 
    if [ "$?" = "0" ] ; then 
    echo "[docker-exec] skipping docker start, already started" 
    else 
    output=`docker start "$1"` 
    echo "[docker start] $output" 
    fi 
    running=1 
} 

function setup_signals { 
    cid="$1"; shift 
    handler="$1"; shift 
    for sig; do 
    trap "$handler '$cid' '$sig'" "$sig" 
    done 
} 

function handle_signal { 
    echo "[docker-exec] received $2" 
    case "$2" in 
    SIGINT) 
     output=`docker stop -t 5 "$1"` 
     echo "[docker stop] $output" 
     running=0 
     ;; 
    SIGTERM) 
     output=`docker stop -t 5 "$1"` 
     echo "[docker stop] $output" 
     running=0 
     ;; 
    SIGHUP) 
     output=`docker restart -t 5 "$1"` 
     echo "[docker restart] $output" 

     # restart logging 
     docker attach "$1" & 
     kill "$logger_pid" 2> /dev/null 
     logger_pid="$!" 
     ;; 
    esac 
} 

running=0 

setup_signals "$1" "handle_signal" SIGINT SIGTERM SIGHUP 

ensure_started_container "$1" 

docker attach "$1" & 
logger_pid="$!" 

while true; do 
    if [ "$running" = "1" ]; then 
    sleep 1 
    else 
    break 
    fi 
done 

exit_code=`docker wait "$1"` 
exit "$exit_code" 
+8

đặc biệt, '/ opt/myapp' được chạy trong forground và ngăn chặn cái bẫy từ thực hiện. Giải pháp là cập nhật dòng đó để đọc như: '/ opt/webapp &; wait' –

+0

Lý do DV: Các câu trả lời chỉ là các liên kết được coi là câu trả lời nghèo nàn. Điều gì sẽ xảy ra nếu liên kết bị hỏng? –

+0

@ Nick-Humrich WOW thực sự!?! –

11

Cũ câu hỏi, nhưng điều này sẽ làm các trick:

#!/bin/bash 

echo starting up 

exec /opt/myapp 

Để biết chi tiết hãy xem ở đây: http://www.techbar.me/stopping-docker-containers-gracefully/

+0

Cảm ơn bạn rất nhiều! Điều này làm việc như một say mê, và tôi đã xáo trộn cả ngày để tìm câu trả lời! – ollien

2

Kể từ Docker 1.9, bạn có thể sử dụng các hướng dẫn STOPSIGNAL trong Dockerfile của bạn:

STOPSIGNAL signal 

Các STOPSIGNAL đặt tín hiệu cuộc gọi hệ thống sẽ được gửi vào vùng chứa để xuất cảnh . Tín hiệu này có thể là số không hợp lệ phù hợp với vị trí trong bảng syscall của hạt nhân, ví dụ 9 hoặc tín hiệu tên ở định dạng SIGNAME, ví dụ SIGKILL.

Nguồn: https://docs.docker.com/engine/reference/builder/#stopsignal

+1

Lưu ý rằng, tất cả các tín hiệu bạn có thể sử dụng, tín hiệu 9 có lẽ là điều tồi tệ nhất. Nó được gọi là KILL vì nó giết chết quá trình mục tiêu mà không cho nó một cơ hội để làm sạch. Sử dụng nó trên một máy chủ cơ sở dữ liệu cấu hình kém, ví dụ, có thể là thảm họa. –

Các vấn đề liên quan