一、制作可以远程登录的Docker容器,系统是Ubuntu14.04。

这个章节记录下了制作一个支持SSH远程登录的容器的全过程。这篇文章使用 Ubuntu 14.04 做例子。其他的操作系统应该大同小异。

我这种用法,相当于把容器当成了虚拟机。用户可以远程登录容器,在容器内进行各种操作。

第一个要面对的问题是:如何才能让容器持久运行下去?众所周知,容器要运行必须要有一个主进程。如果主进程终止,那么容器就会自动退出。一开始我用 Ubuntu 14.04 的镜像的时候就碰到了这个问题。比如你要是执行如下命令:

docker run --name ubuntu1 -d ubuntu:14.04

那么你会发现容器 ubuntu1 根本没有运行起来:

docer macvlan 修改MTU值 macvlan mac地址_java

因此,我们需要一个程序作为容器的主进程无限执行下去。很多人也把这种无限执行的程序称为守护进程(daemon)。

现在就需要编写一个程序做主进程了。因为我熟悉 Java ,所以我使用 Java 来编写主进程。Java 的开发工具使用 Eclipse 和 Maven。

Eclipse 中点击 File 菜单,选中 New 菜单项,在子菜单中点击 Maven Project。在对话框中选中下面三项: Create a simple projectUser default Workspace locationResolve Workspace projects。 点击 Next ,进入下一步的对话框。Group Id 填写 qst,Artifact Id 填写 dockerCmd,直接点击 Finish 就可以创建项目了。项目文件夹中会自动加入一个 pom.xml 文件。

整个项目只需要一个包和一个 Java 类即可。src/main/java 下的包名是 dockerCmd,包中只有一个类 Main.java。

Main.java 的代码如下:

package dockerCmd;

import java.io.IOException;

/**
 * Docker 容器 Ubuntu 14.04 的主进程,保证容器一直运行。
 * @author 张超
 *
 */
public class Main {

    public static void main(String[] args) {
        try {
            // 启动 ssh 服务。
            Runtime.getRuntime().exec("sudo service ssh start");
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        // 无限循环的主进程。
        while (true){
            try {
                Thread.sleep(30L * 60L * 1000L);
            } catch (InterruptedException e) {

            }
        }
    }

}

pom.xml :

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>qst</groupId>
    <artifactId>dockerCmd</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>dockerCmd.Main</mainClass> <!-- 你的主类名 -->
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

右键点击 dockerCmd 项目,快捷菜单中选择 Run As,子菜单中点击 Maven build... ,弹出对话框。在对话框中, Goals 文本框中填入 clean package,点击 Run 按钮。 在项目文件夹下会生成一个 target 文件夹,里面有个 dockerCmd-0.0.1-SNAPSHOT.jar 文件,就是我们需要的可执行 jar 包。

有了 java 程序后,就可以制作镜像了。

新建一个 名为 qstubuntu-v3 的文件夹,目录结构如下:

qstubuntu-v3
    |
    ├─ dockerCmd-0.0.1-SNAPSHOT.jar
    ├─ Dockerfile
    ├─ jre-8u171-linux-x64.tar.gz
    ├─ sshd_config      
    └─ user.txt

jre-8u171-linux-x64.tar.gz 文件是 Linux 版本的 JRE,你可以从 Oracle 下载,或者这个地址下载:

Dockerfile

FROM ubuntu:14.04
# Set timezone as china/shanghai
RUN cp /usr/share/zoneinfo/PRC /etc/localtime
RUN mkdir /usr/java
# Copy jre install file
COPY jre-8u171-linux-x64.tar.gz /usr/java/
WORKDIR /usr/java/
RUN tar zxvf /usr/java/jre-8u171-linux-x64.tar.gz
RUN rm -rf /usr/java/jre-8u171-linux-x64.tar.gz
# Run server 
RUN mkdir /qst
# Copy app jar file
COPY dockerCmd-0.0.1-SNAPSHOT.jar /qst/
# Install openssh
RUN sudo apt-get update && sudo apt-get install openssh-server -y
# Copy ssh config file.
COPY sshd_config /etc/ssh/
# Change root user's password.
COPY user.txt /qst/
RUN chpasswd < /qst/user.txt
EXPOSE 1-65535
CMD ["/usr/java/jre1.8.0_171/bin/java", "-jar", "/qst/dockerCmd-0.0.1-SNAPSHOT.jar"]

sshd_config

# Package generated configuration file
# See the sshd_config(5) manpage for details

# What ports, IPs and protocols we listen for
Port 22
# Use these options to restrict which interfaces/protocols sshd will bind to
#ListenAddress ::
#ListenAddress 0.0.0.0
Protocol 2
# HostKeys for protocol version 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
#Privilege Separation is turned on for security
UsePrivilegeSeparation yes

# Lifetime and size of ephemeral version 1 server key
KeyRegenerationInterval 3600
ServerKeyBits 1024

# Logging
SyslogFacility AUTH
LogLevel INFO

# Authentication:
LoginGraceTime 120
PermitRootLogin yes
StrictModes yes

RSAAuthentication yes
PubkeyAuthentication yes
#AuthorizedKeysFile %h/.ssh/authorized_keys

# Don't read the user's ~/.rhosts and ~/.shosts files
IgnoreRhosts yes
# For this to work you will also need host keys in /etc/ssh_known_hosts
RhostsRSAAuthentication no
# similar for protocol version 2
HostbasedAuthentication no
# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication
#IgnoreUserKnownHosts yes

# To enable empty passwords, change to yes (NOT RECOMMENDED)
PermitEmptyPasswords no

# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
ChallengeResponseAuthentication no

# Change to no to disable tunnelled clear text passwords
#PasswordAuthentication yes

# Kerberos options
#KerberosAuthentication no
#KerberosGetAFSToken no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes

# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes

X11Forwarding yes
X11DisplayOffset 10
PrintMotd no
PrintLastLog yes
TCPKeepAlive yes
#UseLogin no

#MaxStartups 10:30:60
#Banner /etc/issue.net

# Allow client to pass locale environment variables
AcceptEnv LANG LC_*

Subsystem sftp /usr/lib/openssh/sftp-server

# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication.  Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
UsePAM yes

user.txt

root:123456

把整个 qstubuntu-v3 文件夹上传到装有 Docker 的服务器上,通过 cd 命令进入 qstubuntu-v3 目录,然后执行如下命令 docker build -t qst/qstubuntu:v3 . 就可以了。

二、Centos7如何建立docker的macvlan网络模式,让物理机能和容器通信。

我在虚拟机下安装了一个 centos 7 系统。在centos 7 中实验了 Docker 的 macvlan 网络模式。本章节记录了我的实验过程。

虚拟机软件选择 virtualbox, 版本号是5.2。

首先,我下载了一个 CentOS 安装镜像。打开这个页面:https://www.centos.org/download/ 我选择了 DVD ISO 进行下载。

安装好 virtulabox 后,点击新建按钮,弹出对话框。在对话框中,名称填写server-centos,类型选择 Linux ,版本选择 Other Linux(64-bit),点击下一步。

内存我填写了 4096 M,多少根据自己物理机的实际配置决定。点击下一步。

虚拟硬盘步骤中选择现在创建虚拟硬盘 点击创建。

虚拟硬盘文件类型选择 VDI(VirtualBox磁盘映像),点击下一步。

“存储在物理硬盘上” 这一步的时候,选择动态分配。下一步。

“文件位置和大小”:位置是默认的,当然你也可以选择。大小我填写了40G。点击创建。

然后在窗口左边你就可以看到已经创建好的虚拟机了。这个时候虚拟机没有安装任何操作系统。你需要更改虚拟机的设置。鼠标移动到server-centos 虚拟机上,右键,点击设置。在弹出的对话框中,左侧选择网络。右边会出现四个网卡的选项卡。确保只有第一个网卡被选中 启用网络连接。其他的选项如图所示:

docer macvlan 修改MTU值 macvlan mac地址_java_02

这里要注意,因为使用 macvlan,所以网卡必须允许混杂模式。如果你在物理机上配置,也得确保你的网卡支持混杂模式。为了方便后续安装软件,连接方式选择桥接网卡,这样此虚拟机就加入了物理机的办公局域网中。只要办公环境能上网,这台虚拟机就能上网。同时此虚拟机的IP、网段都是办公局域网的,办公局域网内的其他物理机可以ping通或连接此虚拟机(比如SSH远程登录)。

设置好网络后,左侧栏点击存储,如下图:

docer macvlan 修改MTU值 macvlan mac地址_Docker_03

选择 1 框中,没有盘片菜单项。再点击 2 框中的按钮,在打开的文件选择对话框中选择一开始下载的 CentOS 镜像。点击 OK 关闭对话框,启动虚拟机,进入装机界面。在装机界面中,语言选择中文-简体中文。

装机界面如图:

docer macvlan 修改MTU值 macvlan mac地址_Docker_04

软件选择,点进去后,选择 GUI 就行,其他多余的不用选。

安装位置,点进去后,默认配置,直接点击上方的完成按钮就好。

网络和主机名,点击后进入如下页面:

docer macvlan 修改MTU值 macvlan mac地址_docker_05

右上角,打开状态,并点击完成按钮。

SECURITY POLICY 不需要做任何设置,然后点击开始安装。接着系统进入下图:

docer macvlan 修改MTU值 macvlan mac地址_ubuntu_06

安装提示设置好 ROOT 密码,以及创建用户。

等待安装完成后,进入 CentOS 7 的桌面。在桌面空白处右键弹出快捷菜单,点击“打开终端”。

ip addr 命令查到网卡名称,这里假设网卡的名称是 enp0s3。虽然我在虚拟机中设置了网卡的混杂模式,但是还需要在 CentOS 7 操作系统中打开网卡的混杂模式,命令如下:

ip link set enp0s3 promisc on

为了查看是否已经打开混杂模式,用如下命令

[root@bogon]# ip link show enp0s3
2: enp0s3: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 08:00:27:3a:29:5e brd ff:ff:ff:ff:ff:ff

回显的信息中有 PROMISC ,表示已经打开网卡的混杂模式。注意,重启机器后,混杂模式又会变成关闭状态。

创建 macvlan 模式的 docker 网络,取名为 macnet1:

docker network create -d macvlan --subnet 10.30.1.254/24 --gateway 10.30.1.254 -o parent=enp0s3 macnet1

上面命令的含义解释一下。 –subnet 表示子网,这里 24 表示 IPv4 32位地址的前24位,即 10.30.1 前缀。 –gateway 是网关IP,这里是办公环境的网关。 parent 表示宿主机的网卡名。

创建使用 macnet1 网络的容器:

docker run --network macnet1 --ip=10.30.1.23 --name qu1 -d qst/qstubuntu:v3

这样在其他机器上,就可以通过 IP 直接访问容器,比如 SSH 远程登录。此时容器更像是个虚拟机。需要注意的是,因为使用了macvlan 宿主机和容器之间无法访问,这是由于 Linux 的 macvlan 机制决定的。应该没什么解决方法。