目 录
欢迎 3
适用读者 3
Docker环境的安装 3
Docker Tool Box软件的安装 6
设置远程访问API 7
Docker服务器端访问IP和端口设置 7
通过自签名证书安全认证 10
服务器端签名证书设置 10
客户端签名证书设置 14
Java客户端访问Docker服务器 14
本文档讲述的是在VirtualBox上如何安装和配置Docker服务器,并用Java代码去访问服务器。
本文假设读者已经具有Docker的基本概念并想要进一步了解Docker的安装配置知识。
在Windows下的开发环境中,
我的安装版本是
$ sudo apt-get update
$ sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
$ sudo apt-get update
$ sudo apt-get install -y docker-ce
注:在生产系统上,可能会需要应该安装一个特定版本的Docker CE,而不是总是使用最新版本,先列出来可用的版本:
$ sudo apt-cache madison docker-ce
选择要安装的特定版本,第二列是版本字符串,第三列是存储库名称,它指示包来自哪个存储库,以及扩展它的稳定性级别。要安装一个特定的版本,将版本字符串附加到包名中,并通过等号(=)分隔它们,如:
$ sudo apt-get install docker-ce=
$ sudo systemctl status docker
$ sudo systemctl start docker
$ sudo docker run hello-world
管理docker容器中的数据 http://www.cnblogs.com/imoing/p/dockervolumes.html
Docker 常用命令http://www.cnblogs.com/me115/p/5539047.html
Docker容器中文件的上传与下载 https://blog.csdn.net/zzy1078689276/article/details/77389177
Docker实践(二):容器的管理(创建、查看、启动、终止、删除) https://blog.csdn.net/u010246789/article/details/53958662
Docker容器查看进程号码https://blog.csdn.net/mrliqifeng/article/details/62884342
详解如何查看 docker 容器使用的资源 https://www.jb51.net/article/128134.htm
VirtualBox虚拟机网络设置(四种方式)https://blog.csdn.net/zhaihaifei/article/details/53309137
另外:作为学习材料,有一个很好的,几乎是傻瓜式安装的软件叫Docker Tool Box,大家可以下载下来学习。这个软件Docker公司和社区提供的一个集Docker、Virtual Box、Docker管理客户端一体的平台。下载网址是https://docs.docker.com/toolbox/toolbox_install_windows/
作为初学者,它很适合。可以在其上学习使用Docker命令。
Docker命令学习,参照:http://www.runoob.com/docker/docker-tutorial.html
Docker 常用命令,参照:http://www.cnblogs.com/me115/p/5539047.html
我们安装完毕了Docker以后,登录到虚拟机以后,就通过sudo docker一些列命令可以创建管理一个docker container实例,但是,我们的目的不是在虚拟机环境下管理docker container,而是通过Java程序来管理。目前有两个比较著名的Java API for Docker(https://github.com/docker-java/docker-java),一个是Docker Java,一个是Spotify的Docker Client API(https://github.com/spotify/docker-client)。这两个API,我都用过,现在我们九一第二个Docker Java作为公司使用API来,搭建公司的Docker底层平台的基础设施。
首先我们要在Docker的引擎端,来开放API访问。Docker为C/S架构,服务端为docker daemon,客户端为docker.service。支持本地unix socket域套接字通信与远程socket通信。默认为本地unix socket通信,要支持远程客户端访问需要做设置。关于设置daemon监听连接,网上有很多种说法,无外乎以下几种(公司仅用Ubuntu,因此只关注Ubuntu下的设置):
$sudo nano /etc/docker/daemon.json,
添加如下行:
{"hosts": ["fd://", "tcp://0.0.0.0:2375"]}
然后重启Docker,$sudo service docker restart
这种方法我试过了,不管用!不知道为什么。我用的VirtualBox是5.2.12,Ubuntu本本是18.04,Docker(Client/Server)版本是18.05.0-ce
进入编辑模式($sudo nano /etc/default/docker),添加如下行:
DOCKER_OPTS="-H fd:// -H tcp://0.0.0.0:2375"
然后重启Docker,$sudo service docker restart
这种方法我也试过了,不起效果!
$sudo service docker status
出现如下输出:
这让我看到,docker启动的时候,实际是读取docker.service这个文件里的配置的。
我们用命令编辑这个文件:$sudo nano /lib/systemd/system/docker.service
我打开这个文件内容如下:
上图的红框中的文字是决定了docker的通讯监听的。这个文件是docker daemon启动的时候要读取的。是在当前版本(18.05.0-ce)下至关重要的一个配置文件。未来docker的版本上,有可能不一样,因此不可照搬。
我把端口监听加入到上述配置中,配图如下:
-H tcp://0.0.0.0:2375(-H tcp://0.0.0.0:2376),参数H是表示主机(HOST)IP,0.0.0.0,是表示接受任何IP的访问,这样有点风险,不过后边我们会加强安保的。-H fd://是默认Unix协议通讯的意思,也就是很多文章提到的,-H unix:///var/run/docker.sock,于-H fd://是一个意思。在Linux下的Docker的client端于server端的通讯就是基于unix协议的。
加入上述行以后,按Ctrl+X键,根据提示按Y键,保存退出。
要想让配置生效,首先要重新装载配置文件,用如下命令来重新装载:
$sudo systemctl daemon-reload,回车
$sudo service docker restart,回车
$sudo service docker status,来查看。
再用$sudo netstat -lt,列出来用tcp协议监听端口的进程,如下图:
这里我们可以看到[::]:2376,我们这里加的-H tcp://0.0.0.0:2376。因此是2376端口。这说明我们加2376端口监听成功。而前面的tcp6说明是IPv6协议的,而tcp是IPv4的,这里有必要简单说一下,现在Docker进程监听的协议都是tcp6的,经过配置可以改成IPv4的,但是在IPv6中,也可以接收IPv4发过来的请求。因此不必担心tcp和tcp6的差别。
这样,我们成功的使docker开始监听2375或2376,理论上docker已经可以接收远程访问了。
但是,我们上面讲了,开放这个端口,会带来极大的安全隐患,即使有了防火墙设置。因为通讯的内容是没有加密的。因此,我们需要加强安保措施。怎么加强呢?且听下回分解
现在Docker Java API默认的连接方式就是基于签名证书认证的。如果我们的Docker没有签名认证过,Docker Java是无法连接到Docker的,也就是说,要想连Docker,必须做签名认证。
证书的生成: 详细信息,移步官网:Protect the Docker daemon socket(https://docs.docker.com/engine/security/https/#create-a-ca-server-and-client-keys-with-openssl)。其原理是通过指定tlsverify标志并将Docker的tlscacert标志指向受信任的CA证书来启用TLS。在守护进程模式下,它只允许来自由该CA签名的证书认证的客户端的连接。 在客户端模式下,它将只连接到具有由该CA签名的证书的服务器。
现在我们将认证流程简化一下。
下列一系列的命令,让我们可以生成认证证书。注意:下面这些TLS命令将只在Linux上生成一组有效的证书。 macOS附带的OpenSSL版本与Docker所需的证书不兼容。我没有Mac笔记本,所以没有机会试一试,请大家自行试试吧。
首先,我们需要选择一个放证书的文件夹,这个文件夹很多文章,包括官网都建议创建一个.docker文件夹,我个人认为,这个文件夹在哪里不重要,只要能保证服务器安全,防火墙有效,就可以了。
我在/home/xuanqi/下面创建了一个/certs/文件夹。用$pwd,就可以看到该文件夹是/home/xuanqi/certs/。转到该文件夹,执行如下命令:
$ openssl genrsa -aes256 -out ca-key.pem 4096,生成CA私钥,并设置pass phrase,我设置的就是123456,比较简单,因为是测试环境。但是要记住这个密码,后边命令还会用到。再输入:
$ openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem,生成CA公钥,也就是证书。还让你输入国家名,省名啥的,这些都是随便填一个就行,因为密钥算法会把这些信息加密进密钥的。值得一提的是Common Name,说是要你填写,server FQDN或your name,意味着可以随便写,但是我在这里建议,写Docker所在服务器的IP,这个很重要。这个IP后边还会用到,我这里是192.168.99.101,在生产环境下,用使用你docker宿主机的DNS name替换下面的填入Common name,如api.google.com等,这个IP不难拿到,你用$ifconfig命令就可以拿到。我在这里填CDH是错误的。
这样客户端的公钥和私钥就生成完了。出现如下图的画面。
下一步生成服务器私钥,命令如下:
$openssl genrsa -out server-key.pem 4096
再用私钥生成服务器公钥请求文件,也就是证书,命令如下:
$openssl req -subj "/CN=192.168.99.101" -sha256 -new -key server-key.pem -out server.csr,
这里的192.168.99.101同样是Docker所在服务器的IP,你不要照抄,用自己的Docker服务器替换上去。
下面我们可以用CA来签署证书了。这里我们可以填写IP地址或则DNS name,如,我们需要允许10.10.10.20和127.0.0.1连接:
$echo subjectAltName = IP:10.10.10.20, IP:127.0.0.1 > extfile.cnf,
上述命令有点像一个过滤器,如果地址填的不全,远程API就无法访问该Docker,那么我们就把,地址填的全一些,我的命令是这样滴:
$echo subjectAltName = DNS:192.168.99.101, IP: 192.168.99.101, IP: 192.168.1.101, IP:0.0.0.0, IP:127.0.0.1 > extfile.cnf
我填写了,Docker所在服务器(Docker的宿主机)所在地址,域名192.168.99.101等,以及我自己本地客户机所在IP:192.168.1.101,还有Docker所在服务器的本地地址127.0.0.1。免得Java API连接时候找不到,哈哈。
然后,将上述多个生成信息,写入文件。用如下命令。
$openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extfile extfile.cnf
再看客户端私钥:
$openssl genrsa -out key.pem 4096
下一步再生成客户端证书请求文件:
$openssl req -subj '/CN=client' -new -key key.pem -out client.csr
用CA为客户端签署证书文件:
$openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out cert.pem -extfile extfile.cnf
这时候,还需要输入你的密码,我的密码是123456,输上去即可。
这样认证文件就在你的目录下生成完毕了。我的在我的/home/xuanqi/certs,如下图中红色方框所示:
有了证书,不能放在那里不用,Docker不知道你为它生成了证书,得让知道你为它付出的脑细胞。怎么让它知道呢?
还是要回到我们上文提到的docker.service文件中,那个文件里需要添加上你为它生成的文件的路径和文件名。如下图红色方框所示:
字比较小啊看不清。嗯,我们来把它放大:
ExecStart=/usr/bin/dockerd -D --tlsverify=true --tlscert=/home/xuanqi/certs/server-cert.pem --tlskey=/home/xuanqi/certs/server-key.pem --tlscacert=/home/xuanqi/certs/ca.pem -H tcp://0.0.0.0:2376 -H fd://
注意到没有,我这里把所有的认证文件都加上了准确的路径。用Ctrl+X,按Y保存退出。
再重新装载配置文件
$sudo systemctl daemon-reload,回车
$sudo service docker restart,回车
$sudo service docker status,来查看进程状态。
输出结果如下图所示:
至此,服务器端的设置已经完成。
聪明的读者,我想你们已经看出来了,实际上我们在生成服务器端的安全认证证书的同时,已经把客户端的安全认证证书生成了。那么这些证书不能让他们闲在服务器上,需要拿到客户端来来让他们工作。
我把他们下载下来,放到我的本地机上,d:/data/certs/文件夹下,如下图蓝色方框部分,这样Java客户端就可以通过这些证书来访问Docker服务器了。
下面我们来说明一下如何使用这些证书来访问Docker服务器。
我们用Java Docker客户端接口包来访问Docker服务器。
我的Maven项目中使用的依赖是:
<dependency>
<groupId>com.github.docker-javagroupId>
<artifactId>docker-javaartifactId>
<version>3.0.14version>
dependency>
Java代码,这段代码是连接了Docker服务器,并创建了一个Tomcat Container,首先需要你自己去Docker仓库去拉一个Tomcat镜像回来,在Docker所在服务器上用命令$sudo docker pull tomcat,这个镜像比较大,需要一些时间,请耐心等待。
public class DockerJavaClient {
public DockerJavaClient() {
}
public static void main(String[] args) {
DockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder().withDockerTlsVerify(true)
.withDockerCertPath("D:/Data/cert/").withDockerHost("tcp://192.168.99.101:2376")
.withDockerConfig("D:/Data/cert/").withApiVersion("1.23").withRegistryUrl("https://index.docker.io/v1/")
.withRegistryUsername("dockeruser").withRegistryPassword("ilovedocker")
.withRegistryEmail("[email protected]").build();
DockerClient dockerClient = DockerClientBuilder.getInstance(config)
.withDockerCmdExecFactory(dockerCmdExecFactory).build();
CreateContainerResponse container1 = dockerClient.createContainerCmd("tomcat:latest").exec();
dockerClient.startContainerCmd(container1.getId()).exec();
}
至此,我们的Docker访问就配置成功了。