我使用GNU/make(linux(来包装一些docker命令,我不是每天都使用docker,所以我很快就会忘记用法,其中一个包装器是make serve
,它以php -S
(内置服务器(作为命令运行docker run
,它启动并侦听连接。
要停止它,我应该使用^C,我认为(但我不确定(问题是make
拦截信号,make的目标失败,但php进程(和docker实例(仍在运行,我必须手动停止它。
我尝试传递--sig-proxy=true
和false
,但没有效果,但我正在使用伪终端(-t
(运行实例,所以这是意料之中的事。
我写了一个bash包装器,当一些信号被捕获时(EXIT TERM SIGTERM SIGQUIT KILL SIGKILL
(和exec php -S
会回显一些消息,但我没有看到任何消息。
如果信号(以及什么(只传播到分叉的sh -c
,我不确定在运行的make上按下^C时会发生什么,以及为什么docker run
不起作用。
我想知道是否有其他人解决了这个问题,或者是否有人能想出其他解决方案。
编辑
Makefile
:
all:
.PHONY: docker-build serve
docker-build:
docker build -f Dockerfile -t sigtest:v1 .
serve:
docker run -t --rm sigtest:v1 gosu ubuntu:ubuntu php7.0 -S 0.0.0.0:8081 -t /home/ubuntu
Dockerfile
:
FROM ubuntu:16.04
RUN apt-get update &&
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends php7.0-cli gosu
RUN useradd -ms /bin/bash ubuntu
用make docker-build
和make serve
测试
第二次编辑
我设法用shell脚本包装了docker run
(我不确定posix shell中的陷阱语法,最终我会看看(
make
似乎是第一次发送INT
,然后是EXIT
#!/bin/sh
pid=$$
trap 'trap - INT EXIT; echo " signal received, wait..."; docker stop -t 0 sig${pid}; exit' INT EXIT
docker run --name=sig${pid} "$@"
然后在CCD_ 20 中
serve:
-./docker-run.sh -t --rm sigtest:v1 gosu ubuntu:ubuntu php7.0 -S 0.0.0.0:8081 -t /home/ubuntu
我希望不必说出这些例子的名字,但这是我能想到的最简单的方法。
问题不在于使用make
,而在于信号处理。这是一篇描述它的文章
正如我之前所说,docker-compose
管理您服务的整个生命周期。
以下是使用docker-compose
的应用程序的基本示例。通过make up
和make down
(包括^C
(,您可以启动和停止您的服务。Makefile
:
all:
.PHONY: docker-build serve
build:
docker-compose build
up:
docker-compose up
down:
docker-compose down
docker-compose.yml
:
version: '3.3'
services:
my_service:
build: .
ports:
- "8080:8080"
Dockerfile
:
FROM ubuntu:16.04
RUN apt-get update &&
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends php7.0-cli gosu
RUN useradd -ms /bin/bash ubuntu
RUN mkdir -p /home/ubuntu
RUN php7.0 --version
ENTRYPOINT php7.0 -S 0.0.0.0:8080