如何编写一个 Dockerfile,我可以启动服务和 运行 一个 shell 并接受 shell 的参数?
How to write a Dockerfile which I can start a service and run a shell and also accept arguments for the shell?
在 Dockerfile 中,最新的指令是:
CMD sudo chown -R user:user /home/user/che && \
sudo service docker start && \
cd /home/user/che/bin/ && ./che.sh run
它有效,但我无法将更多参数传递给 ./che.sh
。
che.sh
检查内部 docker
是否在完成其他任务后启动。它可以接受几个可选参数,比如 -r:111.111.111.111
。
我尝试将指令修改为:
RUN sudo chown -R user:user /home/user/che && \
sudo service docker start
ENTRYPOINT ["/home/user/che/bin/che.sh"]
为了像 docker run -it --priviledged my/che -r:111.111.111.111 run
一样调用它,但是 che.sh
shell 会报告内部 docker
工作不正常。
我也试过:
ENTRYPOINT ["sudo service docker start", "&&", "/home/user/che/bin/che.sh run"]
甚至:
ENTRYPOINT ["sh", "-c" "sudo service docker start && /home/user/che/bin/che.sh run"]
但是它会报告 sudo service docker start
没有在 $PATH 中找到,或者 che.sh
没有 运行。
正确的写法是什么?
sudo service docker start
应该 运行 当 che.sh
被调用时
- 我需要从外部向
che.sh
传递参数,例如 docker run -it --priviledged my/che -r:111.111.111.111 run
尝试:
1。在 Dockerfile
RUN sudo chown -R user:user /home/user/che && \
sudo service docker start
ENTRYPOINT ["/bin/sh", "-c", "/home/user/che/bin/che.sh run"]
- 启动容器
docker run -it --priviledged my/che -r:111.111.111.111
您必须在 Docker 容器中使用 supervisord,以便在创建容器时能够使用更复杂的 shell 语法。
Docker 关于 supervisord 的文档:https://docs.docker.com/engine/articles/using_supervisord/
当您使用 $ docker run
命令创建新容器时,您可以使用更复杂的 shell 语法(您想要使用的),但是这在 systemd 服务文件中不起作用(由于限制在 systemd 中)和 docker-compose .yml 文件以及 Docker 文件。
首先,您必须在 Docker 文件中安装 supervisord:
RUN apt-get -y update && apt-get -y dist-upgrade \
&& apt-get -y install \
supervisor
RUN mkdir -p /var/log/supervisord
将其放在 Docker 文件的末尾:
COPY etc/supervisor/conf.d/supervisord.conf /etc/supervisor/conf.d/
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"]
在 Docker 文件旁边的 etc/supervisor/conf.d/supervisord.conf
中创建一个文件:
[unix_http_server]
file=/var/run/supervisord.sock
chmod=0777
chown=root:root
username=root
[supervisord]
nodaemon=true
user=root
environment=HOME="/root",USER="root"
logfile=/var/log/supervisord/supervisord.log
pidfile=/var/run/supervisord.pid
childlogdir=/var/log/supervisord
logfile_maxbytes=10MB
loglevel=info
[program:keepalive]
command=/bin/bash -c 'echo Keep Alive service started... && tail -f /dev/null'
autostart=true
autorestart=true
stdout_events_enabled=true
stderr_events_enabled=true
stdout_logfile=/var/log/supervisord/keepalive-stdout.log
stdout_logfile_maxbytes=1MB
stderr_logfile=/var/log/supervisord/keepalive-stderr.log
stderr_logfile_maxbytes=1MB
[program:dcheck]
command=/bin/bash -c 'chmod +x /root/dcheck/repo/dcheck.sh && cd /root/dcheck/repo && ./dcheck.sh'
autostart=true
autorestart=true
stdout_events_enabled=true
stderr_events_enabled=true
stdout_logfile=/var/log/supervisord/dcheck-stdout.log
stdout_logfile_maxbytes=10MB
stderr_logfile=/var/log/supervisord/dcheck-stderr.log
stderr_logfile_maxbytes=1MB
这是一个更复杂的 supervisord.conf,您可能不需要这里的许多命令,而且您必须根据需要更改文件位置。但是,您可以从脚本的 bash 输出中了解如何创建日志文件。
稍后您必须 docker exec
在该容器中,您可以通过以下方式查看 real-time 日志:
docker exec -it your_running_container /bin/bash -c 'tail -f /var/log/supervisord/dcheck-stdout.log'
您可以选择使用 loglevel=debug
在主监督日志中显示子进程日志,但是这充满了时间戳和注释,而不是像 运行 时那样的纯 bash 输出] 直接脚本。
正如您在我的 scipt 中看到的那样,我使用 tail -f /dev/null
使容器保持活动状态,但这是一种不好的做法。 .sh 脚本应该让您的容器自己保持活动状态。
当您将 scipt 作为 ENTRYPOINT ["sudo service docker start", "&&", "/home/user/che/bin/che.sh run"]
发送到 ENTRYPOINT 时,您想要将默认的 docker ENTRYPOINT 从 /bin/sh -c
更改为 sudo
(同时,使用完整的位置名称).
有两种方法可以更改 Docker 文件中的 docker ENTRYPOINT。一种是将其放在 Docker 文件的头部:
RUN ln -sf /bin/bash /bin/sh && ln -sf /bin/bash /bin/sh.distrib
或将其放在底部:
ENTRYPOINT ['/bin/bash', '-c']
当你发送任何 CMD
到这个 Docker 文件后,它将被 /bin/bash -c
命令运行。
还有一点要注意,第一个命令使用 PID1,所以如果你想在我的 supervisord 脚本中 运行 没有 tail -f /dev/null
的 .sh 脚本,它将使用 PID1 进程,并且CTRL+C 命令将不起作用。您必须从另一个 shell 实例关闭容器。
但是,如果您 运行 使用以下命令:
[program:dcheck]
command=/bin/bash -c 'echo pid1 > /dev/null && chmod +x /root/dcheck/repo/dcheck.sh && cd /root/dcheck/repo && ./dcheck.sh'
echo pid1 > /dev/null
将采用 PID1 和 SIGTERM,SIGKILL 和 SIGINT 将再次与您的 shell 脚本一起工作。
我尽量远离 运行宁 Docker 带有 --privileged
标志。您有更多选择来摆脱限制。
我对您的堆栈一无所知,但通常最好不要 docker在容器中使用 Docker。为什么 sudo service docker start
在你的 Docker 文件中有具体原因?
我对这个容器一无所知,它必须是活的吗?因为如果没有,有一个更简单的解决方案,只有在容器必须从命令行处理某些内容时才 运行ning 容器。将此文件放在主机上,名称为 run
让我们说在 /home/hostuser
文件夹中并给它 chmod +x run
:
#!/bin/bash
docker run --rm -it -v /home/hostuser/your_host_shared_folder/:/root/your_container_shared_folder/:rw your_docker_image "echo pid1 > /dev/null && chmod +x /root/script.sh && cd /root && ./script.sh"
在这种情况下,ENTRYPOINT 最好是 ENTRYPOINT ['/bin/bash', '-c']
。
运行 主机上的此脚本:
$ cd /home/hostuser
$ ./run -flag1 -flag2 args1 args2 args3
在 Dockerfile 中,最新的指令是:
CMD sudo chown -R user:user /home/user/che && \
sudo service docker start && \
cd /home/user/che/bin/ && ./che.sh run
它有效,但我无法将更多参数传递给 ./che.sh
。
che.sh
检查内部 docker
是否在完成其他任务后启动。它可以接受几个可选参数,比如 -r:111.111.111.111
。
我尝试将指令修改为:
RUN sudo chown -R user:user /home/user/che && \
sudo service docker start
ENTRYPOINT ["/home/user/che/bin/che.sh"]
为了像 docker run -it --priviledged my/che -r:111.111.111.111 run
一样调用它,但是 che.sh
shell 会报告内部 docker
工作不正常。
我也试过:
ENTRYPOINT ["sudo service docker start", "&&", "/home/user/che/bin/che.sh run"]
甚至:
ENTRYPOINT ["sh", "-c" "sudo service docker start && /home/user/che/bin/che.sh run"]
但是它会报告 sudo service docker start
没有在 $PATH 中找到,或者 che.sh
没有 运行。
正确的写法是什么?
sudo service docker start
应该 运行 当che.sh
被调用时- 我需要从外部向
che.sh
传递参数,例如docker run -it --priviledged my/che -r:111.111.111.111 run
尝试:
1。在 Dockerfile
RUN sudo chown -R user:user /home/user/che && \
sudo service docker start
ENTRYPOINT ["/bin/sh", "-c", "/home/user/che/bin/che.sh run"]
- 启动容器
docker run -it --priviledged my/che -r:111.111.111.111
您必须在 Docker 容器中使用 supervisord,以便在创建容器时能够使用更复杂的 shell 语法。
Docker 关于 supervisord 的文档:https://docs.docker.com/engine/articles/using_supervisord/
当您使用 $ docker run
命令创建新容器时,您可以使用更复杂的 shell 语法(您想要使用的),但是这在 systemd 服务文件中不起作用(由于限制在 systemd 中)和 docker-compose .yml 文件以及 Docker 文件。
首先,您必须在 Docker 文件中安装 supervisord:
RUN apt-get -y update && apt-get -y dist-upgrade \
&& apt-get -y install \
supervisor
RUN mkdir -p /var/log/supervisord
将其放在 Docker 文件的末尾:
COPY etc/supervisor/conf.d/supervisord.conf /etc/supervisor/conf.d/
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"]
在 Docker 文件旁边的 etc/supervisor/conf.d/supervisord.conf
中创建一个文件:
[unix_http_server]
file=/var/run/supervisord.sock
chmod=0777
chown=root:root
username=root
[supervisord]
nodaemon=true
user=root
environment=HOME="/root",USER="root"
logfile=/var/log/supervisord/supervisord.log
pidfile=/var/run/supervisord.pid
childlogdir=/var/log/supervisord
logfile_maxbytes=10MB
loglevel=info
[program:keepalive]
command=/bin/bash -c 'echo Keep Alive service started... && tail -f /dev/null'
autostart=true
autorestart=true
stdout_events_enabled=true
stderr_events_enabled=true
stdout_logfile=/var/log/supervisord/keepalive-stdout.log
stdout_logfile_maxbytes=1MB
stderr_logfile=/var/log/supervisord/keepalive-stderr.log
stderr_logfile_maxbytes=1MB
[program:dcheck]
command=/bin/bash -c 'chmod +x /root/dcheck/repo/dcheck.sh && cd /root/dcheck/repo && ./dcheck.sh'
autostart=true
autorestart=true
stdout_events_enabled=true
stderr_events_enabled=true
stdout_logfile=/var/log/supervisord/dcheck-stdout.log
stdout_logfile_maxbytes=10MB
stderr_logfile=/var/log/supervisord/dcheck-stderr.log
stderr_logfile_maxbytes=1MB
这是一个更复杂的 supervisord.conf,您可能不需要这里的许多命令,而且您必须根据需要更改文件位置。但是,您可以从脚本的 bash 输出中了解如何创建日志文件。
稍后您必须 docker exec
在该容器中,您可以通过以下方式查看 real-time 日志:
docker exec -it your_running_container /bin/bash -c 'tail -f /var/log/supervisord/dcheck-stdout.log'
您可以选择使用 loglevel=debug
在主监督日志中显示子进程日志,但是这充满了时间戳和注释,而不是像 运行 时那样的纯 bash 输出] 直接脚本。
正如您在我的 scipt 中看到的那样,我使用 tail -f /dev/null
使容器保持活动状态,但这是一种不好的做法。 .sh 脚本应该让您的容器自己保持活动状态。
当您将 scipt 作为 ENTRYPOINT ["sudo service docker start", "&&", "/home/user/che/bin/che.sh run"]
发送到 ENTRYPOINT 时,您想要将默认的 docker ENTRYPOINT 从 /bin/sh -c
更改为 sudo
(同时,使用完整的位置名称).
有两种方法可以更改 Docker 文件中的 docker ENTRYPOINT。一种是将其放在 Docker 文件的头部:
RUN ln -sf /bin/bash /bin/sh && ln -sf /bin/bash /bin/sh.distrib
或将其放在底部:
ENTRYPOINT ['/bin/bash', '-c']
当你发送任何 CMD
到这个 Docker 文件后,它将被 /bin/bash -c
命令运行。
还有一点要注意,第一个命令使用 PID1,所以如果你想在我的 supervisord 脚本中 运行 没有 tail -f /dev/null
的 .sh 脚本,它将使用 PID1 进程,并且CTRL+C 命令将不起作用。您必须从另一个 shell 实例关闭容器。
但是,如果您 运行 使用以下命令:
[program:dcheck]
command=/bin/bash -c 'echo pid1 > /dev/null && chmod +x /root/dcheck/repo/dcheck.sh && cd /root/dcheck/repo && ./dcheck.sh'
echo pid1 > /dev/null
将采用 PID1 和 SIGTERM,SIGKILL 和 SIGINT 将再次与您的 shell 脚本一起工作。
我尽量远离 运行宁 Docker 带有 --privileged
标志。您有更多选择来摆脱限制。
我对您的堆栈一无所知,但通常最好不要 docker在容器中使用 Docker。为什么 sudo service docker start
在你的 Docker 文件中有具体原因?
我对这个容器一无所知,它必须是活的吗?因为如果没有,有一个更简单的解决方案,只有在容器必须从命令行处理某些内容时才 运行ning 容器。将此文件放在主机上,名称为 run
让我们说在 /home/hostuser
文件夹中并给它 chmod +x run
:
#!/bin/bash
docker run --rm -it -v /home/hostuser/your_host_shared_folder/:/root/your_container_shared_folder/:rw your_docker_image "echo pid1 > /dev/null && chmod +x /root/script.sh && cd /root && ./script.sh"
在这种情况下,ENTRYPOINT 最好是 ENTRYPOINT ['/bin/bash', '-c']
。
运行 主机上的此脚本:
$ cd /home/hostuser
$ ./run -flag1 -flag2 args1 args2 args3