Docker容器启动时启动服务
在使用Docker快速部署不同版本CentOS容器介绍了如何构建运行CentOS的容器,这样我们可以快速clone出多个以相同image构建的CentOS环境。
在Dockerfile中有很多RUN指令告诉docker在构建容器的时候需要完成哪些工作。但是要注意,这个RUN指令只在构建容器的时候运行一次,用于初始化容器。但是容器停止然后再次启动,则不会运行。
这样,对于我们每次启动容器都要运行的服务,该如何调用呢?
docker提供了另外一个指令 CMD,该指令在容器每次启动时都会执行,这样就可以在容器中启动服务,例如sshd。
举例:
这里同时添加了一个
authorized_keys到容器中方便ssh登陆,所以在Dockerfile的相同目录下还要再准备一个从authorized_keys文件
FROM docker.io/centos:7
MAINTAINER vincent huatai <vincent@huatai.me>
RUN yum clean all
RUN yum -y update
#RUN yum -y install which sudo mlocate net-tools rsyslog file ntp ntpdate \
#wget tar bzip2 screen sysstat unzip nfs-utils parted lsof man bind-utils \
#gcc gcc-c++ make telnet flex autoconf automake ncurses-devel crontabs \
#zlib-devel git openssh-clients openssh-server initscripts
RUN yum -y install which sudo openssh-clients openssh-server initscripts
# Prepare sshd host key
RUN ssh-keygen -A
# add account "admin" and give sudo privilege
RUN groupadd -g 505 admin
RUN useradd -g 505 -u 505 -d /home/admin -m admin
RUN usermod -aG wheel admin
RUN echo "%wheel ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
# Add ssh public key for login
RUN mkdir -p /home/admin/.ssh
ADD authorized_keys /home/admin/.ssh/authorized_keys
RUN chown -R admin:admin /home/admin/.ssh
RUN chmod 600 /home/admin/.ssh/authorized_keys
RUN chmod 700 /home/admin/.ssh
# run service when container started
EXPOSE 22
#CMD /usr/sbin/sshd,this is not a interactive shell
CMD ["/usr/sbin/sshd", "-D"]
sshd的参数-D是一个前台debug参数:
-D When this option is specified, sshd will not detach and does not become a daemon. This allows easy monitoring of sshd.注意:这里
EXPOSE 22(等同于命令行--expose=22或-p 22)会将容器的22端口随机映射到host主机的网络对外网络接口上,此时就可以通过docker port <容器名>查看端口映射,即可使用动态映射的端口从外部网络访问虚拟容器的ssh服务。如果要固定映射,则配置为
EXPOSE 22:8022;命令行使用-p 22:8022将容器ssh端口映射成物理服务器的8022端口。
构建镜像
docker build -t local:centos7 .创建容器
docker run -d -P --hostname dev7 --name dev7 local:centos7这里不要使用
docker run -it进入交互模式(最后启动的是bash会导致替换掉Dockerfile中的最后的CMD ["/usr/sbin/sshd", "-D"])-- 注意:
Dockerfile最后的CMD指令会被docker run ... /bin/bash替换,命令行的CMD优先级高。
如果使用如下名林启动/bin/bash则会进入交互模式,此时不会启动sshd,但是可以在交互模式中使用手工命令/usr/sbin/sshd启动ssh服务:
docker run -it --hostname dev7 --name dev7 local:centos7 /bin/bashDockerfile中CMD和ENDPOINT的区别
CMD和ENDPOINT的区别上述容器化sshd有一个非常麻烦的地方是,无法docker attach访问容器内部系统(因为最后一个CMD是/usr/sbin/sshd -D占用了控制台),对于传统的系统维护带来不便。
但是如上所述,如果在docker run命令行传递需要运行的指令/bin/bash虽然可以获得终端交互,但是带来上述CMD ["/usr/sbin/sshd", "-D"]被覆盖,就不能自动启动ssh服务。
解决的方法是使用ENDPOINT,这个方式的指令不会被命令行指令覆盖。此外,可以在ENDPOINT部分使用&&来连续处理多个服务启动,并最后执行/bin/bash来获得一个交互终端:
ENTRYPOINT /usr/sbin/sshd && /bin/bash然后按照以下方式创建镜像和启动容器:
docker build -t local:centos7 .
docker run -itd --hostname dev7 --name dev7 local:centos7注意:
docker run参数要使用-it,这样表示启动一个pty(-t)和交互模式(-i),以避免/bin/bash指令立即结束。如果没有-it参数,则容器瞬间启动并结束(因为/bin/bash已经执行结束了)。docker run参数使用-d表示detach,这样可以断开容器终端,让容器中的/bin/bash继续运行。这样也就达到了随时可以重新用docker attach dev7重新连接到虚拟容器进行进一步操作。
完整Dockerfile
# HowTo use this dockerfile?
# ------ for example:
# 1. create image which name "local:centos7"
# 2. create container which name "dev7"
# --------------------------------------
# docker build -t local:centos7 .
# docker run -itd --hostname dev7 --name dev7 local:centos7
FROM docker.io/centos:7
MAINTAINER vincent huatai <vincent@huatai.me>
RUN yum clean all
RUN yum -y update
RUN yum -y install which sudo openssh-clients openssh-server initscripts
# Prepare sshd host key
RUN ssh-keygen -A
# add account "admin" and give sudo privilege
RUN groupadd -g 505 admin
RUN useradd -g 505 -u 505 -d /home/admin -m admin
RUN usermod -aG wheel admin
RUN echo "%wheel ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
# Add ssh public key for login
RUN mkdir -p /home/admin/.ssh
ADD authorized_keys /home/admin/.ssh/authorized_keys
RUN chown -R admin:admin /home/admin/.ssh
RUN chmod 600 /home/admin/.ssh/authorized_keys
RUN chmod 700 /home/admin/.ssh
# run service when container started - sshd
EXPOSE 22
#CMD ["/usr/sbin/sshd", "-D"]
# ----------
# WANT run sshd and get a bash
# ENTRYPOINT will not be override by commandline
# ----------
ENTRYPOINT /usr/sbin/sshd && /bin/bash其他服务启动案例
以下案例同时创建了共享存储和端口映射
# creat host share storage volume
docker volume create share-data
# create container with port 8000 map
docker run -itd -p 22 -p 8000:8000 --memory=2048M --cpus="1.5" --hostname dev7 --name dev7 \
-v share-data:/data local:centos7或者简化一些:
docker run -itd --hostname dev7 --name dev7 -v share-data:/data local:centos7最新的Dockerfile见我的DevOps: Docker: CentOS7
参考
Last updated
Was this helpful?