Docker的安装与使用
Docker的安装与使用
什么是Docker?
Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app), 更重要的是容器性能开销极低。
关键字:容器虚拟化技术
需要准备
- Centos7.x系统、64位系统、内核版本3.10以上
或
Centos6.5以上系统、64位系统、内核版本2.6.32以上 - Centos必须能够联网
如何查看Liunx系统内核?
1 | uname -r |
1 | lsb_release -a |
如果满足了上面的条件、我们现在就开始吧!
Docker概念
docker主机(Host):
安装了Docker程序的机器(Docker直接安装在操作系统之上);docker客户端(Client):
连接docker主机进行操作;docker仓库(Registry):
用来保存各种打包好的软件镜像;docker镜像(Images):
软件打包好的镜像;放在docker仓库中;docker容器(Container):
镜像启动后的实例称为一个容器;容器是独立运行的一个或一组应用;
安装 Docker
需要提前安装的必备组件: gcc gcc-c++ (如果安装了可以忽略)
1
2yum -y install gcc
yum -y install gcc-c++卸载旧版本Docker (如果没有安装可以忽略)
1
yum -y remove docker docker-common docker-selinux docker-engine
安装需要的软件包
1
yum install -y yum-utils device-mapper-peristent-data lvm2
如果yum被其他进程占用、
ps -ef|grep yum
查看占用进程kill -9 占用的端口号
就可以了。设置镜像仓库地址
1
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
更新yum软件包索引
1
yum makecache fast
安装Docker CE
1
yum -y install docker-ce
启动Docker
1
2systemctl start docker //启动Docker
systemctl status docker //查看启动状态其他
1
2
3
4
5
6
7docker version //查看版本
docker run hello-world //运行helloworld镜像(没有会从远程仓库pull)
卸载
systemctl stop docker
yum -y remove docker-re
rm -rf /var/lib/docker
yum install -y epel-release
1
Docker使用EPEL发布,RHEL系的OS首先要确保已经持有EPEL仓库,否则先检查OS的版本,然后安装相应的EPEL包。
yum install -y docker-io
安装后的配置文件:
/etc/sysconfig/docker
启动Docker后台服务:
service docker start
docker version
验证
配置镜像加速
使用阿里云镜像加速(https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors)
Docker常用命令
帮助命令
docker version //Docker版本
docker info //Docker详细信息
docker help //Docker命令信息
镜像命令
docker images //列出本地主机上的镜像
REPOSITORY TAG IMAGE ID CREATED SIZE 表示镜像的仓库源 镜像的标签 镜像ID 镜像创建时间 镜像大小 可加参数:
参数 说明 -a
列出本地所有的镜像(含中间映像层) -q
只显示镜像ID --digests
只显示镜像的摘要信息 --no-trunc
显示完整的镜像信息 docker search 镜像名字 //从云端查询指定镜像
NAME DESCRIPTION OFFICIAL STARTS AUTOMATED 镜像仓库源的名称 镜像的描述 是否 docker 官方发布 类似 Github 里面的 star,表示点赞、喜欢的意思 自动构建 可加参数:
参数 说明 --no-trunc
显示完整的镜像描述 -s 数字
列出收藏数不小于指定值的镜像) --automated
只列出 automated bulid
类型的镜像docker pull 镜像名字[:TAG] //从云端下载指定镜像
docker rmi 镜像ID //删除本地指定镜像
可加参数:
参数 说明 -f
强制删除某个镜像 例:docker rmi -f fce289e99eb9 -f 镜像名1:TAG 镜像名2:TAG
强制删除多个镜像 例:docker rmi -f hello-world tomcat -f $(docker images -qa)
强制删除所有本地镜像
容器命令
docker run [OPTIONS]
IMAGE
[COMMAND] [ARG…] //新建并启动容器参数 说明 --name="容器新名字"
为容器指定一个名字 -d
后台运行容器,并返回容器ID,也启动守护式容器 -i
以交互模式运行容器,通常与 -t 同时运行 -t
为容器重新分配一个伪输入终端,通常与 -i 同时运行 -P
随机端口映射 -p
指定端口映射,有以下四种格式: ip:hostPort:containerPort ip::containerPort hostPort:containerPort 主机端口:容器端口 containerPort docker ps [OPTIONS] //列出当前所有正在运行的容器
参数 说明 -a
列出当前所有 正在运行的容器
+历史上运行过的
-l
显示最近创建的容器 -n
显示最近n个创建的容器 例:docker ps -n 3 -q
静默模式,只显示容器编号
--no-trunc
随机端口映射 退出容器
参数 说明 exit
容器停止退出 Ctrl+P+Q
容器不停止退出 docker start 容器ID或者容器名 //启动容器
docker restart 容器ID或者容器名 //重启容器
docker stop 容器ID或者容器名 //停止容器
docker kill 容器ID或者容器名 //强制停止容器
docker rm 容器ID //删除已经停止容器
参数 说明 docker rm -f $(docker ps -a -q)
一次性删除多个容器 docker ps -a -q|xargs docker rm
容器不停止退出 docker commit 提交容器副本使之成为一个新的镜像
1
docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名[:标签名]
参数 说明 -a
提交的镜像作者 -c
使用Dockerfile指令来创建镜像 -m
提交时的说明文字 -p
在commit时,将容器暂停 docker inspect 镜像ID //获取容器/镜像的元数据、返回一个 JSON 文件记录着 Docker 容器的配置和状态信息。
参数 说明 -f
指定返回值的模板文件 -s
显示总的文件大小 --type
为指定类型返回JSON
注意
启动守护式容器
docker run -d 容器名
1
2
3
4
5
6
7
8
9使用镜像centos:latest以后台模式启动一个容器
docker run -d centos
问题:然后docker ps -a进行查看,会发现容器已经退出
很重要的要说明的一点:Docker容器后台运行就必须有一个前台进程
容器运行的命令如果不是那些一直挂起的命令(比如运行top,tail),就是会自动退出的。1
2docker run -d centos /bin/sh -C "while true;do echo hello zykj;sleep 2;done"
启动时给centos一些参数、可以让容器不停止运行、死循环输出日志查看容器日志
docker logs -f -t –tail 容器ID
参数 说明 -t
是加入时间戳 -f
跟随最新的日志打印 --tail
数字显示最后多少条
查看容器内运行的进程
1
docker top 容器ID
进入正在运行的容器以命令行交互
docker exec -it 容器ID bashShell //不进入容器里执行容器命令
1
2
3
4以Centos为例:
docker exec -it 容器ID ls -l /tmp
docker exec -it 容器ID /bin/bash //进入交互模式重新进入docker attach 容器ID
区别:
exec
: 是在容器中打开新的终端,并且可以启动新的进程attach
: 直接进入容器启动命令的终端,不会启动新的进程从容器内拷贝文件到主机上
1
docker cp 容器ID:容器内路径目的主机路径
Docker容器数据卷
docker的理念将运行的环境打包形成容器运行,运行可以伴随容器,但是我们对数据的要求是希望持久化,容器之间可以共享数据,Docker容器产生的数据,如果不通过docker commit生成新的镜像,使得数据作为容器的一部分保存下来,那么当容器被删除之后,数据也就没了,为了能够保存数据,在docker容器中使用卷。卷就是目录或者文件,存在于一个或者多个容器中,但是不属于联合文件系统,因此能够绕过Union File System提供一些用于持久化数据或共享数据的特点。
关键字:容器的持久化
、容器间继承+共享数据
数据卷
容器内添加
直接命令添加
命令
1
2
3
4
5
6
7
8
9
10
11
12docker run -it -v /宿主机绝对路径目录:/容器内目录 镜像名
例:(ps:目录不存在会自动创建)
docker run -it -v /myDataVolume:/dataVolumeContianer centos
通过docker inspect查看
"VolimesRW":{
"/dataVolumeContainer": true
},
Docker挂载主机目录Docker访问出现cannot open directory : Permission denied
解决办法:在挂载目录后多加一个--privileged=true参数即可容器和宿主机之间会数据共享
容器停止退出后,主机修改后数据同样数据同步
命令(带权限:主机目录创建文件、容器目录只读)
1
2
3
4
5
6docker run -it -v /宿主机绝对路径目录:/容器内目录:ro镜像名
通过docker inspect查看
"VolimesRW":{
"/dataVolumeContainer": false
},
Dockerfile添加
根目录(其他目录也可以)下新建mydocker文件夹并进入
1
2cd /
mkdir mydocker可在Dockerfile中使用VOLUME指令来给镜像添加一个或多个数据卷
1
2
3
4
5VOLUME["/dataVolumeContainer","/dataVolumeContainer2","/dataVolumeContainer3"]
说明:
出于可移植和分享的考虑,用 -v主机目录:容器目录这种方法不能够直接在Dockerfile中实现。
由于宿主机目录是依赖于特定宿主机的,并不能够保证在所有的宿主机上都存在这样的特定目录。File构建
1
2
3
4
5
6
7
8
9
10vim Dockerfile
# volume test
FROM centos
VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
CMD echo "Hello,-----world!"
CMD /bin/bash
通过docker命令解释就是:
docker run -it -V /host1: /dataVolumeContainer1 -v /host2:/dataVolumeContainer2 centos /bin/bashbuild后生成镜像 获得一个新镜像zykj/centos
1
2
3
4
5docker build -f /mydocker/Dockerfile -t zykj/centos .
-f :指定要使用的Dockerfile路径;
--tag, -t: 镜像的名字及标签,通常 name:tag 或者 name 格式;可以在一次构建中为一个镜像设置多个标签。
. :当前目录run容器
数据卷容器
命名的容器挂载数据卷,其它容器通过挂载这个(父容器)实现数据共享,挂载数据卷的容器,称之为数据卷容器
容器间数据共享 - -volumes-from
命令
1
docker run -it --name 子容器 --volumes-from 父容器 zykj/centos
结论:容器之间配置信息的传递,数据卷的生命周期一直持续到没有容器使用它为止
DockerFile
Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。
构建三个步骤
- 编写Dockerfile文件
- docker build
- docker run
Dockerfile构建过程解析
Dockerfile内容基础知识
1 | 每条保留字指令都必须为大写字母且后面要跟随至少一个参数 |
Docker执行Dockerfile的大致流程
1 | docker从基础镜像运行一个容器 |
总结:
1 | Dockerfile,需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉 及的内容包括执行代码或者是文件、环境 |
Docker体系结构(保留字指令)
FROM
基础镜像,当前新镜像是基于哪个镜像的MAINTAINER
镜像维护者的姓名和邮箱地址RUN
容器构建时需要运行的命令EXPOSE
当前容器对外暴露出的端口WORKDIR
指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点(就是工作目录)ENV
用来在构建镜像过程中设置环境变量1
2
3
4
5
6ENV MY_PATH /usr/mytest
这个环境变量可以在后续的任何RUN指令中使用,这就如同在命令前面指定了环境变量前缀一样;
也可以在其它指令中直接使用这些环境变量
比如: WORKDIR $MY_PATHADD
将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL
和解压tar压缩包
,类似ADD,拷贝文件和目录到镜像中。COPY
将从构建上下文目录中<源路径>的文件/目录复制到新的一层的镜像内的<目标路径>位置1
2
3两种方法:
COPY src dest
COPY ["src","dest"]VOLUME
容器数据卷, 用于数据保存和持久化工作CMD
Dockerfile中可以有多个CMD指令,但
只有最后一个生效
,CMD 会被docker run之后的参数替换
1
2
3
4
5
6CMD容器启动命令
CMD指令的格式和RUN相似,也是两种格式:
● shell格式: CMD <命令>
● exec格式: CMD ["可执行文件","参数1", "参数2" ...]
● 参数列表格式: CMD ["参数1","参数2"...]。在指定了 ENTRYPOINT 指令后,用 CMD 指定具体的参数。指定一个容器启动时要运行的命令口
ENTRYPOINT
- 指定一个容器启动时要运行的命令
- ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序及参数
ONBUILD
当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后父镜像的onbuild被触发
案例
Base镜像(scratch)
DockerHub中99%的镜像都是通过在base镜像中安装和配置需要的软件构建出来的
1 | docker pull centos |
自定义镜像mycentos
- 编写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16vim Dockerfile
FROM centos
MAINTAINER zykj<zykj@zykj.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "success-------------ok"
CMD /bin/bash - 构建
1
2
3docker build 镜像名字:TAG .
例:docker build -f /mydocker/Dockerfile mycentos:1.3 . - 运行
1
docker run -it 镜像名字:TAG
- 列出镜像的变更历史
1
docker history 镜像ID
CMD/ENTRYPOINT案例
都是指定一个容器启动时要运行的命令
CMD
- Dockerfile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换
- 运行tomcat docker run -it -p 8888:8080 tomcat ls -l
ENTRYPOINT
- docker run之后的参数会被当做参数传递给ENTRYPOINT,之后形成新的命令组合
- 例子
制作
CMD
版可以查询IP信息的容器(curl直接访问http://ip.cn会报403、所以。。。以下告诉方法
)1
2
3FROM centos
RUN yum install -y curl
CMD [ "curl" , "-s" , "http://ip.cn" ]curl命令解释
1
2
3
4
5
6
7
8
9
10curl命令可以用来执行下载、发送各种HTTP请求,指定HTTP头部等操作。
如果系统没有curl可以使用yum install curl安装,也可以下载安装。
curl是将下载文件输出到stdout
使用命令: curl http://www.baidu.com
执行后,www.baidu.com的html就会显示在屏幕上了
这是最简单的使用方法。用这个命令获得了http://curl.haxx.se指向的页面,同样,如果这里的URL指向的是一个文件
或者一幅图都可以直接下载到本地。如果下载的是HTML文档,那么缺省的将只显示文件头部,即HTML文档的
header。要全部显示,请加参数 -i问题 如果我们希望显示HTTP头信息,就需要加上i参数、docker run myip -i 但是会报错
WHY
1
2
3
4
5
6
7我们可以看到可执行文件找不到的报错,executable file not found。
之前我们说过,跟在镜像名后面的是command,运行时会替换CMD的默认值。
因此这里的-i替换了原来的CMD,而不是添加在原来的curl -s htp://ip.cn 后面。而-i根本不是命令,所以自然找不到。
那么如果我们希望加入-i这参数,我们就必须重新完整的输入这个命令:
docker run myip curl -s http://ip.cn -i制作
ENTROYPOINT
版查询IP信息的容器1
2
3FROM centos
RUN yum install -y curl
ENTROYPOINT [ "curl" , "-s" , "http://ip.cn" ]通过使用ENTROYPOINT可以执行docker run myip -i、-i作为参数追加
自定义Tomcat9镜像
mkdir -p /zykjuse/mydockerfile/tomcat9
在上述目录下
touch c.txt
将
jdk
和tomcat
安装的压缩包拷贝进上一步目录在/zykjuse/mydockerfile/tomcat9目录下新建Dockerfile文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24FROM centos
MAINTAINER zykj<zykj@zykj.com>
#把宿主机当前上下文的c.txt拷贝到容器/usr/local/路径下
COPY c.txt /usr/local/cincontainer.txt
#把java与tomcat添加到容器中
ADD jdk-8u171-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.8.tar.gz /usr/local/
#安装vim编辑器
RUN yum -y install vim
#设置工作访问时候的WORKDIR路径,登录落脚点
ENV MYPATH /usr/local
WORKDIR $MYPATH
#配置java与tomcat环境变量
ENV JAVA_HOME /usr/local/jdk1.8.0_171
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.8
ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.8
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
#容器运行时监听的端口
EXPOSE 8080
#启动时运行tomcat
# ENTRYPOINT ["/usr/local/apache-tomcat-9.0.8/bin/startup.sh" ]
# CMD ["/usr/local/apache-tomcat-9.0.8/bin/catalina.sh","run"]
CMD /usr/local/apache-tomcat-9.0.8/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.8/bin/logs/catalina.out构建
1
2docker build -t zykjtomcat9 .
ps:如果Dockerfile在当前目录内可以不指定运行
1
docker run -d -p 9080:8080 --name myt9 -v /zzyyuse/mydockerfile/tomcat9/test:/usr/local/apache-tomcat-9.0.8/webapps/test -v /zzyyuse/mydockerfile/tomcat9/tomcat9logs/:/usr/local/apache-tomcat-9.0.8/logs --privileged=true zykjtomcat9
结合前述容器卷将测试的web服务test发布
在/zykjuse/mydockerfile/tomcat9下创建test目录
1
mkdir test
编写
a.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17vim a.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
-----------welcome------------
<%="i am in docker tomcat self "%>
<br>
<br>
<% System.out.println("=============docker tomcat self");%>
</body>
</html>在当前创建WEB-INF目录
1
mkdir WEB-INF
编写
web.xml
1
2
3
4
5
6
7
8
9
10
11
12
13vim web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>test</display-name>
</web-app>
最后重启容器访问 localhost:9080/test/a.jsp就可以了
小总结
安装软件
安装Tomcat
- docker hub上面查找tomcat镜像(
docker search tomcat
) - 从docker hub上拉取tomcat镜像到本地(
docker pull tomcat
) docker images
查看是否有拉取到的tomcat- 使用tomcat镜像创建容器(也叫运行镜像) (
docker run -it -p 8080:8080 tomcat
)-p
: 主机端口:docker容器端口-P
: 随机分配端口D-i
: 交互-t
: 终端
安装MySQL
- docker hub上面查找mysql镜像
- 从docker hub上(阿里云加速器)拉取mysql镜像到本地标签为5.7
- 使用mysql5.7镜像创建容器(也叫运行镜像)
- 使用mysql镜像命令说明:
1
docker run -p 3306:3306 --name mysql -v /zykjuse/mysql/conf:/etc/mysql/conf.d -v /zzyyuse/mysql/logs:/logs -v /zykjuse/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
1
2
3
4
5
6
7-p 3306:3306:将主机的3306端口映射到docker容器的3306端口。
--name mysql:运行服务名字
-v /zykjuse/mysql/conf:/etc/mysql/conf.d :将主机/zykjuse/mysql目录下的conf/my.cnf 挂载到容器的 /etc/mysql/conf.d
-v /zykjuse/mysql/logs:/logs:将主机/zykjuse/mysql目录下的 logs 目录挂载到容器的 /logs。
-v /zykjuse/mysql/data:/var/lib/mysql :将主机/zykjuse/mysql目录下的data目录挂载到容器的 /var/lib/mysql
-e MYSQL_ROOT_PASSWORD=123456:初始化 root 用户的密码。
-d mysql:5.7 : 后台程序运行mysql5.71
docker exec -it MySQL运行成功后的容器ID /bin/bash
- 外部Win10也来连接运行在docker上的mysql服务
- 数据备份小测试(可以不做)
1
docker exec mysql服务容器ID sh -c ' exec mysqldump --all-databases -uroot -p"123456" ' > /zykjuse/all-databases.sql
- 使用mysql镜像
安装Redis
从docker hub.上(阿里云加速器)拉取redis镜像到本地标签为3.2
使用redis3. 2镜像创建容器(也叫运行镜像)
使用镜像
1
docker run -p 6379:6379 -v /zykjuse/myredis/data:/data -v /zykjuse/myredis/conf/redis.conf:/usr/local/etc/redis/redis.conf -d redis:3.2 redis-server /usr/local/etc/redis/redis.conf --appendonly yes
命令说明:
1
2
3
4
5-p 6379:6379:将主机的6379端口映射到docker容器的3306端口。
-v /zykjuse/myredis/data:/data:将主机/zykjuse/myredis目录下的 data 目录挂载到容器的 /data。
-v /zykjuse/myredis/conf/redis.conf:/usr/local/etc/redis/redis.conf:将主机/zykjuse/myredis/conf/目录下的 redis.conf 目录 挂载到容器的 /usr/local/etc/redis/redis.conf
-d redis:3.2 redis-server: 后台程序运行redis:3.2、redis-server
--appendonly yes:开启AOF模式在主机 /zykjuse/myredis/conf/redis.conf 目录下新建redis.conf文件
1
vim /zzyuse/myredis/conf/redis.conf/redis.conf
redis.conf
在这里可以复制 https://github.com/antirez/redis/blob/unstable/redis.conf测试redis cli连接上来
1
docker exec -it 运行着Rediis服务的容器ID redis-cli
测试持久化文件生成
其他
IDEA整合Docker部署java项目
配置Docker的远程访问
修改/lib/systemd/system/docker.service
1
vim /lib/systemd/system/docker.service
替换ExecStart
1
2
3
4替换
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
为
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock重启Docker服务
1
2systemctl daemon-reload
systemctl restart docker查看2375端口是否被监听
1
netstat -nlpt
服务器防火墙开启2375端口
1
2
3
4
5
6
7
8
9
10
11# 开放2375端口
firewall-cmd --add-port=2375/tcp --permanent
# 重启防火墙(修改配置后要重启防火墙)
firewall-cmd --reload
# 查看开放的端口
firewall-cmd --zone=public --list-ports
# 参数解释
firwall-cmd:是Linux提供的操作firewall的一个工具;
--permanent:表示设置为持久;
--add-port:标识添加的端口;如果是云服务器、那么还要添加安全组规则(这里以阿里云服务器为演示)
验证是否成功
1
2
3
4本地:
curl http://127.0.0.1:2375/version
网页:
http://服务器IP:2375/version
网页访问一样。
IDEA中配置Docker插件
确保IDEA安装Docker插件
打开设置
Settings->Build,Execution,Deployment
、找到Docker添加配置好了会显示
Connection successful
接下来配置镜像加速
点击OK之后,下方控制栏,出现Docker控制台
集成Maven插件
在项目的pom.xml文件中添加以下内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35<properties>
<!--docker镜像的前缀-->
<docker.image.prefix>docker</docker.image.prefix>
</properties>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.0.0</version>
<configuration>
<!--远程Docker的地址-->
<dockerHost>http://localhost:2375</dockerHost>
<!--镜像名称,前缀/项目名-->
<imageName>${docker.image.prefix}/${project.artifactId}</imageName>
<!--指定标签-->
<imageTags>
<imageTag>latest</imageTag>
</imageTags>
<!-- 指定 Dockerfile 路径 ${project.basedir}:项目根路径下-->
<dockerDirectory>src/main/docker</dockerDirectory>
<!-- 这里是复制 jar 包到 docker 容器指定目录配置 -->
<resources>
<resource>
<targetPath>/</targetPath>
<!--jar 包所在的路径 此处配置的 即对应 target 目录-->
<directory>${project.build.directory}</directory>
<!-- 需要包含的 jar包 ,这里对应的是 Dockerfile中添加的文件名 -->
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>根据配置的
<dockerDirectory>src/main/docker</dockerDirectory>
在src
的main
创建docker目录、编写Dockerfile1
2
3
4
5
6
7FROM java:8
VOLUME /tmp
ADD *.jar app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]Maven生成jar包
确保
target
目录下有生成的jar包Maven构建镜像
运行Docker镜像
然而、这样就行了吗?
当然不行的,前面提到的配置是允许所有人都可以访问的,因为docker默认是root权限的,你把2375端口
暴露在外面,意味着别人随时都可以提取到你服务器的root权限,是很容易被黑客全端口扫描,导致被入侵。我们需要继续配置。
Docker CA认证
创建ca文件夹,用于存放CA私钥和公钥
1
2mkdir -p /usr/local/ca
cd /usr/local/ca/创建密码(需要连续输入两次相同的密码)
1
openssl genrsa -aes256 -out ca-key.pem 4096
依次输入密码、国家、省、市、组织名称等(随便输入、影响不大)
1
openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem
生成
server-key.pem
1
openssl genrsa -out server-key.pem 4096
把下面的
$Host
换成你自己服务器外网的IP或者域名1
2
3
4
5openssl req -subj "/CN=$HOST" -sha256 -new -key server-key.pem -out server.csr
例子:
openssl req -subj "/CN=192.168.1.106" -sha256 -new -key server-key.pem -out server.csr
openssl req -subj "/CN=www.baidu.com" -sha256 -new -key server-key.pem -out server.csr配置白名单
配置要允许那些ip可以连接到服务器的docker,因为已经是ssl连接,所以我推荐配置0.0.0.0,也就是所有ip都可以连接(但只有拥有证书的才可以连接成功),这样配置好之后公司其他人也可以使用。如果你不想这样,那你可以配置ip,用逗号分隔开。下面的
$Host
依旧是你服务器外网的IP或者域名,请自行替换。1
2
3填写的是ip地址的话命令如下echo subjectAltName = IP:$HOST,IP:0.0.0.0 >> extfile.cnf
填写的是域名的话命令如下 echo subjectAltName = DNS:$HOST,IP:0.0.0.0 >> extfile.cnf执行命令,将Docker守护程序密钥的扩展使用属性设置为仅用于服务器身份验证
1
echo extendedKeyUsage = serverAuth >> extfile.cnf
执行命令,并输入之前设置的密码,生成签名证书
1
openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem \-CAcreateserial -out server-cert.pem -extfile extfile.cnf
生成客户端的key.pem,到时候把生成好的几个公钥私钥拷出去即可
1
openssl genrsa -out key.pem 4096
执行命令
1
openssl req -subj '/CN=client' -new -key key.pem -out client.csr
执行命令,要使密钥适合客户端身份验证,请创建扩展配置文件
1
echo extendedKeyUsage = clientAuth >> extfile.cnf
生成
cert.pem
,需要输入前面设置的密码,生成签名证书1
openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem \-CAcreateserial -out cert.pem -extfile extfile.cnf
删除不需要的文件,两个证书签名请求
1
rm -v client.csr server.csr
修改权限,要保护您的密钥免受意外损坏,请删除其写入权限。要使它们只能被您读取,更改文件模式
1
chmod -v 0400 ca-key.pem key.pem server-key.pem
证书可以是对外可读的,删除写入权限以防止意外损坏
1
chmod -v 0444 ca.pem server-cert.pem cert.pem
归集服务器证书
1
2
3cp server-*.pem /etc/docker/
cp ca.pem /etc/docker/修改Docker配置,使Docker守护程序仅接受来自提供CA信任的证书的客户端的连接
1
vim /lib/systemd/system/docker.service
将
ExecStart=/usr/bin/dockerd
替换1
ExecStart=/usr/bin/dockerd --tlsverify --tlscacert=/etc/docker/ca.pem --tlscert=/etc/docker/server-cert.pem --tlskey=/etc/docker/server-key.pem -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
重新加载daemon并重启docker
1
2systemctl daemon-reload
systemctl restart docker重启docker
1
service docker restart
复制这几个文件到本地
回到IDEA
重新配置pom文件
1
2<!--CA存放路径-->
<dockerCertPath>D:\ca</dockerCertPath>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37<properties>
<!--docker镜像的前缀-->
<docker.image.prefix>docker</docker.image.prefix>
</properties>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.0.0</version>
<configuration>
<!--远程Docker的地址-->
<dockerHost>http://localhost:2375</dockerHost>
<!--CA存放路径-->
<dockerCertPath>D:\ca</dockerCertPath>
<!--镜像名称,前缀/项目名-->
<imageName>${docker.image.prefix}/${project.artifactId}</imageName>
<!--指定标签-->
<imageTags>
<imageTag>latest</imageTag>
</imageTags>
<!-- 指定 Dockerfile 路径 ${project.basedir}:项目根路径下-->
<dockerDirectory>src/main/docker</dockerDirectory>
<!-- 这里是复制 jar 包到 docker 容器指定目录配置 -->
<resources>
<resource>
<targetPath>/</targetPath>
<!--jar 包所在的路径 此处配置的 即对应 target 目录-->
<directory>${project.build.directory}</directory>
<!-- 需要包含的 jar包 ,这里对应的是 Dockerfile中添加的文件名 -->
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>最后重新生成jar包、重新构建docker镜像就可以了。
参考连接: