最近正在写的某个容器升级了一下架构,在启动容器时需要同时运行一个frps服务。根据我的习惯,一开始打算使用systemctl添加frps服务,然后enable一下以实现开机自启。但在我实际使用时,发现服务没有跑起来。查了一下日志,发现了这条报错:

ERROR:systemctl: frps.service: Executable path is not absolute, ignoring: ./frps -c /frps.ini ERROR:systemctl: Exec is not an absolute path: ExecStart=./frps -c /frps.ini ERROR:systemctl: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ERROR:systemctl: Found 1 problems in /etc/systemd/system/frps.service ERROR:systemctl: The SystemD commands must always be absolute paths by definition. ERROR:systemctl: Earlier versions of systemctl.py did use a subshell thus using $PATH ERROR:systemctl: however newer versions use execve just like the real SystemD daemon ERROR:systemctl: so that your docker-only service scripts may start to fail suddenly. ERROR:systemctl: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

去官网稍微找了下,发现了这段解释:

This is by design. Docker should be running a process in the foreground in your container and it will be spawned as PID 1 within the container’s pid namespace. Docker is designed for process isolation, not for OS virtualization, so there are no other OS processes and daemons running inside the container (like systemd, cron, syslog, etc), only your entrypoint or command you run. If they included systemd commands, you’d find a lot of things not working since your entrypoint replaces init. Systemd also makes use to cgroups which docker restricts inside of containers since the ability to change cgroups could allow a process to escape the container’s isolation. Without systemd running as init inside your container, there’s no daemon to process your start and stop commands.

大意就是:docker只是提供了进程隔离,不是操作系统的虚拟,所以不能运行systemd。

如果只想同时运行两个服务,应该用什么办法呢?其实很简单:在Dockerfile CMD内运行start.sh,然后再用nohup挂起frps服务就好了: nohup ./frps -c /frps.ini & python3 /main.py 顺利运行frps服务。