在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"]
但它会在$ PATH中找不到报告sudo service docker start
,或者che.sh
没有运行。
编写它的正确方法是什么?
sudo service docker start
应在调用che.sh
时运行che.sh
,例如docker run -it --priviledged my/che -r:111.111.111.111 run
答案 0 :(得分:4)
您必须在Docker容器中使用supervisord,以便在创建容器时能够使用更复杂的shell语法。
关于supervisord的Docker文档:https://docs.docker.com/engine/articles/using_supervisord/
当您使用$ docker run
命令创建新容器时,您可以使用更复杂的shell语法(您想要使用),但是这在systemd服务文件中不起作用(由于systemd的限制)和docker-撰写.yml文件和Dockerfiles。
首先,您必须在Dockerfile中安装supervisord:
RUN apt-get -y update && apt-get -y dist-upgrade \
&& apt-get -y install \
supervisor
RUN mkdir -p /var/log/supervisord
将其放在Dockerfile的末尾:
COPY etc/supervisor/conf.d/supervisord.conf /etc/supervisor/conf.d/
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"]
在Dockerfile旁边的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
,您可以使用以下方式实时查看日志:
docker exec -it your_running_container /bin/bash -c 'tail -f /var/log/supervisord/dcheck-stdout.log'
您可以选择使用loglevel=debug
在主Supervisord日志中显示子进程日志,但这里有时间戳和注释,而不是像直接运行脚本时那样的纯bash输出。
正如你在我的scipt中看到的那样,我使用tail -f /dev/null
保持容器,但这是一个不好的做法。 .sh脚本应该让你的容器独立存在。
当你将你的scipt发送到ENTRYPOINT ENTRYPOINT ["sudo service docker start", "&&", "/home/user/che/bin/che.sh run"]
时,你想要将默认的泊坞号ENTRYPOINT从/bin/sh -c
更改为sudo
(同样,使用完整的位置名称)。
有两种方法可以在Dockerfile中更改docker ENTRYPOINT。一种是将它放在Dockerfile的head部分:
RUN ln -sf /bin/bash /bin/sh && ln -sf /bin/bash /bin/sh.distrib
或者将它放在底部:
ENTRYPOINT ['/bin/bash', '-c']
当您向此Dockerfile发送任何CMD
后,它将由/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脚本。
我尝试使用--privileged
标志继续运行Docker。您还有更多选择可以摆脱限制。
我对你的堆栈一无所知,但通常不知道如何不将Docker停靠在Container中。您的Dockerfile中有sudo service docker start
的具体原因吗?
我对这个容器一无所知,是否必须活着?因为如果没有,有一个更简单的解决方案,只有在必须从命令行处理某个东西时才运行容器。将此文件放在名为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
答案 1 :(得分:0)
尝试:
1。在Dockerfile中
class Counter implements Runnable {
private int a = 0;
private int b = 0;
private final Object lock1 = new Object();
private final Object lock2 = new Object();
private void incA() {
++a;
}
private void decA() {
--a;
}
private void incB() {
++b;
}
private void decB() {
--b;
}
private void printValues() {
System.out.println("a: " + a + " | b: " + b);
}
public void run() {
for (int i = 0; i < 10; i++) {
synchronized (lock1) {
incA();
decA();
}
synchronized (lock2) {
incB();
decB();
}
synchronized (lock1) {
synchronized (lock2) {
printValues();
}
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE);
View childLayout = null;
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_home) {
childLayout = inflater.inflate(R.layout.layout1, (ViewGroup) findViewById(R.id.where_to_include));
} else if (id == R.id.nav_menu) {
childLayout = inflater.inflate(R.layout.layout2, (ViewGroup) findViewById(R.id.where_to_include));
} else if (id == R.id.nav_hospital) {
childLayout = inflater.inflate(R.layout.layout3, (ViewGroup) findViewById(R.id.where_to_include));
} else if (id == R.id.nav_atm) {
childLayout = inflater.inflate(R.layout.layout4, (ViewGroup) findViewById(R.id.where_to_include));
} else if (id == R.id.nav_feedback) {
childLayout = inflater.inflate(R.layout.layout5, (ViewGroup) findViewById(R.id.where_to_include));
} else if (id == R.id.nav_about) {
childLayout = inflater.inflate(R.layout.layout6, (ViewGroup) findViewById(R.id.where_to_include));
// then add childLayout to your row
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}