实现你的需求有很多种做法。
1、如果在容器没有启动 sshd 服务的情况下又想通过一条ssh命令就进入容器内部,可以将 docker exec 与 ssh 两条指令结合到一起去:
ssh -t 云主机IP 'docker exec -it mypython bash'
什么?嫌命令太长?用神奇的 alias 啊,想要多短就有多短:
alias sp='ssh -t 云主机IP "docker exec -it mypython bash"'
这样不管你容器内部有没有启动 sshd ,运行 sp 就可以直接进入容器内;
2、既然你的容器是用来运行 python 服务的,那为何不用 supervisor 来管理容器内进程呢 ?supervisor 同时管理 sshd 进程和你自己的 python 服务进程,然后将启动 supervisor 进程的命令作为容器的 entrypoint,这样就能确保每次启动容器的时候既启动了 sshd , 又启动了你自己的 python 服务;
比如我用 supervisor 来同时管理 redis 和 sshd 服务,构建镜像的过程如下:
Dockerfile:
FROM ubuntu:14.04
RUN apt-get update
RUN apt-get install -y openssh-server redis-server supervisor
RUN mkdir -p /var/run/sshd
RUN sed -i 's/daemonize yes/daemonize no/' /etc/redis/redis.conf
RUN sed -i 's/bind 127.0.0.1/bind 0.0.0.0/' /etc/redis/redis.conf
COPY supervisord.conf /etc/supervisor/supervisord.conf
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"]
supervisord.conf
[supervisord]
nodaemon=true
[program:sshd]
command=/usr/sbin/sshd -D
autostart=true
autorestart=true
startsecs=3
[program:redis]
command=/usr/bin/redis-server /etc/redis/redis.conf
autostart=true
autorestart=true
startsecs=3
build 镜像
docker build --network=host -t multi_process:v1 .
构建完成 run 一个容器
docker run -itd --name mp multi_process:v1
然后进入容器查看容器内部进程
docker exec -it mp bash
root@c59c5fca5c53:/# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 11:12 pts/0 00:00:00 /usr/bin/python /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
root 8 1 0 11:12 pts/0 00:00:00 /usr/sbin/sshd -D
root 9 1 0 11:12 pts/0 00:00:00 /usr/bin/redis-server 0.0.0.0:6379
可以看到容器内的 init 进程是 supervisord,然后启动了 sshd 和 redis-server 两个子进程,这样一个容器就能在提供 redis 服务的同时又支持 ssh 登入了。
3、容器传入传出数据,你都用了卷了,所要传输数据的目录也是卷挂载的目录,那直接在宿主机上操作呗,scp 正向 反向都能拷贝
scp -r local/code/path user@云主机IP:~/code
或者
scp -r user@云主机IP:~/code local/code/path
通过宿主机传输跟通过容器直接传输是一样的;
4、不建议以脚本形式在 entrypoint 里同时启动 sshd 和你自己的 python 服务进程,为什么呢?因为这样做会导致的容器关闭时进程能不能有效回收的问题,如果容器内进程不能正常回收,就会出现僵尸进程,而Docker 本身只是进程隔离,处理这些僵尸进程有时需要重启宿主机,如果宿主机运行多个容器的话,其他的服务就跟着受影响了。