共5 个小时13分钟
docker run不时候要修改容器的默认端口号, 不然网络不通;
IDEA 配置dockerca的时候disconnected before any data was received:
- 配置白名单的时候需要加入服务器自身的ip;echo subjectAltName =IP:139.129.118.96,IP:0.0.0.0>> extfile.cnf
★★上传到远程服务器的时候一定要上加TLSv1.2;mvn clean package docker:build -Djdk.tls.client.protocols=TLSv1.2
不然会报证书扩展名错误 [extension (5) should not be presented in certificate_request]
解决方案:水平扩展(不断加服务器) , 满足高并发.
maven:
Docker
IaaS:Infrastrcure as a service 基础设施即服务
PaaS:Platform as a service 平台即服务
SaaS:Software as a service 软件即服务
实现原来技术不同
使用资源不同
特性 | 容器 | 虚拟机 |
---|---|---|
启动 | 秒级 | 分钟级 |
硬盘使用 | 一般为MB | 一般为GB |
性能 | 接近原生 | 弱于 |
形同支持量 | 单机支持上千个容器 | 一般几十个 |
镜像 容器 仓库
docker | 面向对象 | |
---|---|---|
容器 | 对象 | |
镜像 | 类 |
docker镜像 仓库:
分层存储
保存镜像
官方提供了docker registry 镜像
)
Either pass the --registry-mirror
option when starting dockerd
manually, or edit /etc/docker/daemon.json
and add the registry-mirrors
key and value, to make the change persistent.
{
"registry-mirrors": ["https://<my-docker-mirror-host>"]
}
阿里云加速器
daocloud加速器
docker pull [选项] [Docker Registry 地址[:端口]/] 仓库名[:标签]
docker pull tomcat:版本号
(不写版本号 则laster版本)docker image ls
docker images
docker images -q
:查看id docker image prune
删除前须确认没有被任何容器使用
docker image rm [选项] <镜像1> [<镜像2>....]
docker image rmi 镜像id
docker ps
docker ps -a //全部容器 包括运行和退出的
docker container ls
docker container ls -a
docker run --rm -d --name tomcat001 -p 10082:8080 tomcat
-i 保持docker和同容器内的交互,启动容器时候,运行的命令经书后,容器依然存活,没有退出 (默认是会退出的)
以交互模式运行容器,通常与 -t 同时使用;
-t 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
-d 后台运行容器
--rm 容器启动后 执行完成停止命令 或程序后就销毁
--name 给容器起个名字
-p 宿主机:内部端口
docker start <id> // 停止正在运行的容器 或者ctrl +c
docker container stop <id|name>
docker start <id>
docker restart <id>
docker rm <id>
docker exec -it 容器id(name ) bash
-i -t 参数
退出: exit
docker cp [options] container:path localpath
容器复制到宿主机docker cp [options] localpath container:path
宿主机复制到容器中
# 复制到容器
docker cp /data/files2.jpeg tomcat001:/usr/local/tomcat/webapps/ROOT/1.jpeg
# 把容器中的复制出来
docker cp tomcat001:/usr/local/tomcat/webapps/ROOT/index.jsp ./
# 修改后再复制回去
docker cp index.jsp tomcat001:/usr/local/tomcat/webapps/ROOT/
docker logs 容器id/name
docker logs -f -t --since="2021-06-04" --tail=10 tomcat004
—since :指定输出日志的开始日期
-f 查看实时日志
-t 查看日志的产生日期
-tail=10 查看最后10条日志
tomcat004 容器ming
1. 上传项目
2. 关闭已经启动的tomcat
docker stop id1 id2
docker ps -a
docker rm id
docker images
docker run --rm -d --name test1 -p8080:8080 tomcat
docker run --rm -d --name test2 -p8081:8081 tomcat
docker run --rm -d --name test3 -p8082:8082 tomcat
docker exec -it test1 base
docker cp test test1:/usr/local/tomcat/test1/webapps/
docker stop id 会销毁 —rm 启动的容器的文件/
docker volume create vol1
查看所有的数据卷 docker volume ls
docker inspect vol1
-v 宿主机目录 容器id:docker目录
docker run --rm -d --name test1 -p8080:8080 -v /data/docker/test110 test1:/usr/local/webapps/test001 tomcat
docker pull nginx
docker run --name nginx8001 -p 8001:80 -d nginx
docker run --rm -d -p 8001:80 --name nginx8001 \
-v /data/docker-data/vo1001/nginx8001/html:/usr/share/nginx/html \
-v /home/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \
-v /data/docker-data/vo1001/nginx8001/logs:/var/log/nginx \
nginx
docker run --rm -d -p 8081:80 --name nginx-test-web \
-v /home/nginx/www:/usr/share/nginx/html \
-v /home/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \
-v /home/nginx/logs:/var/log/nginx \
nginx
命令说明:
—rm:容器终止运行后,自动删除容器文件。
-p 8081:80: 将容器的 80 端口映射到主机的 8082 端口.
—name nginx-test-web:将容器命名为 nginx-test-web
-v /home/nginx/www:/usr/share/nginx/html:将我们自己创建的 www 目录挂载到容器的 /usr/share/nginx/html。
-v /home/nginx/conf/nginx.conf:/etc/nginx/nginx.conf:将我们自己创建的 nginx.conf 挂载到容器的 /etc/nginx/nginx.conf。
-v /home/nginx/logs:/var/log/nginx:将我们自己创建的 logs 挂载到容器的 /var/log/nginx。
官网查看: https://hub.docker.com/
下载镜像: docker pull mysql:5.7
创建并启动mysql
docker run -d --name mysql5.7-3308 -p 3308:3306 -e MYSQL_ROOT_PASSWORD='root' mysql:5.7
外部登录: mysql -h 127.0.0.1 -P 3308 -uroot -p
内部登录
授权远程访问:
grant all privileges on *.* to 'root'@'%' identified by 'root' with grant option;
flush privileges;
- 从已经创建的容器中更新镜像,并且提交这个景象
- 使用dockerfile指令来创建一个新的镜像
镜像的定制实际上就是定制每一层锁添加的配置, 文件.
把每一层修改, 安装, 构建, 操作的命令都写入一个脚本, 用这个脚本来构建,定制镜像, 那么之前提及的无法重复,的问题, 体积的问题就都会解决. 这个脚本就是Dockerfile.
Dockerfile是一个文本文件, 其内包含一条条指令(Instruction), 每一条指令构建一层, 因此每一条指令的内容, 就是描述该层应当如何构建.
基础镜像不存在会在docker hub上拉取(一般会是文件的第一个指令)
使用格式:
FROM <镜像>:[tag]
FROM <镜像>@digest[校验码]
当前主机没有此镜像时, 会自动去官网hub下载
[逐渐废弃]
LABEL — 替代MAINTAINER
具体使用:
LABEL maintainer=”作者信息”
使用格式:
MAINTAINER "lcxm <xuduochoua@163.com>"
LABEL maintainer="NGINX Docker Maintainers <docker-maint@nginx.com>"
LABEL "com.example.vendor"="acme incorpor ated"
LABEL "com.example.label-with-value"="foo"
LABEL version="1.0"
LABEL description=" this text illustrates \
thatlabe-values惨审判multiplelines"
设置的环境变量查看: docker inspect
修改环境变量: docker run —env <key>=<value>
具体用法
ENV JAVA_HOME /usr/local/jdk
ENV JRE_HHOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib;$JRE_HOME/lib/
ENV PATH $PATH;$JAVA_HOME/bin/
docker默认的工作目录是 /, 只有run能执行cd命令切换目录, 而且还是作用在当下的run, 也就是说每个run都是独立运行的.
如果想让其他指令在指定的目录下执行, 就用workdir. rowrkdir动作的目录改变是持久的.
workdir /usr/local/tomcat
卷: 只能定义docker管理的卷
volume/data/mysql 运行的时候回随机在宿主机的目录下生成一个卷目录
文件要在dockerfile工作目录
src: 源文件,
- 支持通配符
- 通常项目路径
dest: 目标路径
- 通常绝对路径
add 将文件从路径 <src> 复制添加到容器内部路径<dest>
<src> 必须是相对于源文件夹的一个文件或目录, 也可以是一个远程url
<dest>是目标容器中的绝对路径. 所有的新文件和文件夹都会创建UID和GID.
事实上如果<src>是一个远程文件ur, 那么目标文件的权限将会是600;
使用格式:
EXPOSE 80/tcp 23/udp
不加协议默认为tcp
不加协议默认为tcp
使用-P选项可以暴露这里指定的端口
但是宿主的关联至这个端口的端口是随机的
由于命令行的强大能力, run指令在定制镜像时是最常用的指令之一.
其格式有两种:
- shell格式: run <命令> 就像直接在命令行输入命令一样
- exec格式: run [“可执行文件”,”参数1”,”参数2”] , 这更像是函数调用中的格式
使用格式
run <command>
run [“<executable>“, “param1”, “param2”]
# 1 创建dockerfile /usr/local/docker/demo1
vim Dockerfile
# 2 写入内容
FROM tomcat //指定tomcat最新版本镜像
LABEL MAINTAINER "lcxm <xuduochoua@163.com>"
RUN echo 'hello world' > /usr/local/tomcat/webapps/ROOT/index.html
# 3 构建镜像 -t 镜像名称 demo1:1.0
docker build -t demo1 .
# 4 运行镜像
docker run -d --rm --name demo1-8081 -p 8081:8080 demo1
删除ROOT下的其他所有文件
Dockerfile
from tomcat
LABEL MAINTAINER "lcxm <xuudochoua@163.com>"
WORKDIR /usr/local/tomcat/webapps/ROOT/
RUN rm -rf *
WORKDIR /usr/local/tomcat
RUN echo 'hello world 002' > /usr/local/tomcat/webapps/ROOT/index.html
docker build -t demo002 .
docker run -d —rm —name demo002-8082 -p 8082:8080 demo002
基于上一个镜像, 外部复制一个文件,复制到容器中 并且能够访问
加一句命令
COPY 1.png /usr/local/tomcat/webapps/ROOT
FROM tomcat
LABEL MAINTAINER "lcxm <xuudochoua@163.com>"
WORKDIR /usr/local/tomcat/webapps/ROOT/
RUN rm -rf *
WORKDIR /usr/local/tomcat/webapps
COPY 1.png /usr/local/tomcat/webapps/ROOT
RUN echo 'hello world 002' > /usr/local/tomcat/webapps/ROOT/index.html
利用Dockerfile 将一个war包生成生成镜像的Dockerfile
FROM tomcat
LABEL MAINTAINER "lcxm <xuudochoua@163.com>"
WORKDIR /usr/local/tomcat/webapps/ROOT/
RUN rm -rf *
WORKDIR /usr/local/tomcat/webapps
# 复制到root下
COPY test.zip /usr/local/tomcat/webapps/ROOT
# 解压 然后删除原zip
RUN unzip test.zip
RUN rm -rf text.zip
WORKDIR /usr/local/tomcat
准备好打包好的jar: test-1.0.0.jar
在同目录下创建Dockerfile文件
# 基础镜像 即运行环境
FROM java:8
LABEL MAINTAINER "lcxm <xuudochoua@163.com>"
# 创建tmp目录并持久化到docker数据文件夹,因springboot使用内嵌tomcat容器默认使用/tmp作为工作目录
VOLUME /temp
# 复制文件并重命名
ADD test-1.0.0.jar test.jar
#并非真正的发布端口,这个只是容器部署人员之间的交流,即简历image的人员告诉容器部署人员容器应该映射那个端口给外界
EXPOSE 8080
#容器启动时运行的命令,相当于命令行输入java -jar xxx.jar, 为了缩短tomcta启动时间,添加java.security.egd的系统属性指向/dev/./urandom作为ENTRYPOINT
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar", "/test.jar"]
希望能完成以下工作:
- 在IDEA中开发代码
- 代码达成jar
- 部署到linux服务器上
- 如果用docker(编写dockerfile文件)
- 构建镜像
- 运行容器
#修改docker服务文件
vim /lib/systemd/system/docker.service
#修改ExecStart这行
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
# 重新加载配置文件
systemctl daemon-reload
# 重启服务
systemctl restart docker.service
# 查看端口是否开启
netstat -nlpt
# 没有netstat命令 可先安装 yum install net-tools
# 查看是否生效
curl http://127.0.0.1:2375/info
file - setting - plugins - install ….
docker integration
传统过程中: 打包, 部署, 上传到linux, 编写dockerfile, 构建镜像, 创建容器运行
在持续集成过程中,
docker-maven-plugin插件: 在maven工程中,通过简单的配置,自动生成镜像,并推送到仓库中
pom.xml
<properties>
<docker.image.prefix>lcxm</docker.image.prefix>
</properties>
<build>
<plugins>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.0.0</version>
<configuration>
<!-- 镜像名称 -->
<imageName>${docker.image.prefix}/${project.artifactId}</imageName>
<!-- 指定标签 -->
<imageTags>
<imageTag>lastest</imageTag>
</imageTags>
<!--基础镜像 jdk1.8 -->
<baseImage>java</baseImage>
<maintainer>lcxm xuduochoua@163.com</maintainer>
<!-- 切换到ROOT目录 -->
<workdir>/ROOT</workdir>
<cmd>["java", "-version"]</cmd>
<entryPoint>["java", "-jar", "${project.build.finalName}.jar"]</entryPoint>
<!-- 指定dockerfile路径 -->
<!--
<dockerDirectory>${project.basedir}/src/main/docker</dockerDirectory>
-->
<!--指定远程docker api地址 -->
<dockerHost>http://xuqiudong.cn:2375</dockerHost>
<!-- 这里是复制 jar 包到 docker 容器指定目录配置 类似add中的target -->
<resources>
<resource>
<targetPath>/ROOT</targetPath>
<!-- 用于指定需要复制的根目录 ${project.build.directory} 表示target目录-->
<directory>${project.build.directory}</directory>
<!--用于指定需要复制的文件${project.build.finalName}.jar指的是打包后的jar包文件 类似add中的 目标 --> <include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
</plugins>
</build>
FROM java
LABEL MAINTAINER "lcxm <xuudochoua@163.com>"
WORKDIR /ROOT
ADD /ROOT/xxx.jar /ROOT/
ENTRYPOINT ["java","-jar", "xxx.jar"]
CMD ["java", "-version"]
打包.并构建镜像到docker上去
mvn clean package docker:build
在打包的时候就实现并构建镜像到docker上去
<executions>
<!-- 当执行mvn package 时 执行mvn clean package docker:build -->
<execution>
<id>build-image</id>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
<!-- 当执行mvn package时 回对镜像进行标签设定 -->
<execution>
<id>tag-image</id>
<phase>package</phase>
<goals>
<goal>tag</goal>
</goals>
</execution>
</executions>
官方demo示例:https://docs.docker.com/engine/security/protect-access/
Now that you have a CA, you can create a server key and certificate signing request (CSR). Make sure that “Common Name” matches the hostname you use to connect to Docker:
echo subjectAltName = DNS:$HOST,IP:10.10.10.20,IP:127.0.0.1 >> extfile.cnf
After generating
cert.pem
andserver-cert.pem
you can safely remove the two certificate signing requests and extensions config files:
To protect your keys from accidental damage, remove their write permissions. To make them only readable by you, change file modes as follows:
Certificates can be world-readable, but you might want to remove write access to prevent accidental damage:
复制证书到
/etc/docker/
下
Now you can make the Docker daemon only accept connections from clients providing a certificate trusted by your CA:
修改docker服务文件
vim /lib/systemd/system/docker.serviceExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
修改为:
ExecStart=/usr/bin/dockerd —tlsverify —tlscacert=/data/docker-data/dockerca/ca.pem —tlscert=/data/docker-data/dockerca/server-cert.pem —tlskey=/data/docker-data/dockerca/server-key.pem -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
# 1 创建目录存放ca的公钥和私钥,并进入 /data/docker-data/dockerca/
# 2生成ca私钥和公钥 phrase pass: 654321
openssl genrsa -aes256 -out ca-key.pem 4096
# 3 补全ca证书信息 654321 cn anhui hefei pers pers pers pers xuduochoua@163.com
openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem
#4 生成server-key.pem
openssl genrsa -out server-key.pem 4096
#5 ca 来签公钥
openssl req -subj "/CN=139.129.118.96" -sha256 -new -key server-key.pem -out server.csr
# 6 配置白名单 需要加入服务器本身的ip地址 不然报错disconnected before any data was received
echo subjectAltName =IP:139.129.118.96,IP:0.0.0.0>> extfile.cnf
#7 将docker守护程序秘钥的扩展使用属性设置为服务器身份验证
echo extendedKeyUsage = serverAuth >> extfile.cnf
# 8 生成签名证书 654321
openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem \
-CAcreateserial -out server-cert.pem -extfile extfile.cnf
#9 生成客户端的key.pem
openssl genrsa -out key.pem 4096
openssl req -subj '/CN=client' -new -key key.pem -out client.csr
#10要使秘钥适合客户端身份验证
echo extendedKeyUsage = clientAuth > extfile.cnf
echo extendedKeyUsage = clientAuth > extfile-client.cnf
#11 现在 生成签名证书 654321
openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem \
-CAcreateserial -out cert.pem -extfile extfile-client.cnf
#12 删除不要需要的文件, 两个证书签名请求
rm -v client.csr server.csr extfile.cnf extfile-client.cnf
#13 可修改权限
chmod -v 0400 ca-key.pem key.pem server-key.pem
chmod -v 0444 ca.pem server-cert.pem cert.pem
#14 归集服务器证书
cp server-*pem /etc/docker/
cp ca.pem /etc/docker/
# 15 修改docker配置
vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd --tlsverify --tlscacert=/data/docker-data/dockerca/ca.pem --tlscert=/data/docker-data/dockerca/server-cert.pem --tlskey=/data/docker-data/dockerca/server-key.pem -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
# 16 重新加载damnon 并重启docker
systemctl daemon-reload
systemctl restart docker
# 17 开发2375端口
/sbin/iptables -I INPUT -p tcp --dport 2375 -j ACCEPT
# 18 重启docker
systemctl restart docker
ca.pem ca-key.pem cert.pem key.pem
tcp://xuqiudong.cn:2375
改为:
并且配置秘钥的文件夹
修改pom.xml中的dockerhost 对应的ip为https
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.2.2</version>
<executions>
<execution>
<id>build-image</id>
<!--将插件绑定在package这个phase上。也就是说,用户只需执行mvn package ,就会自动执行mvn docker:build -->
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- 镜像名称 -->
<imageName>${docker.image.prefix}/${project.artifactId}</imageName>
<!-- 指定标签 -->
<imageTags>
<imageTag>lastest</imageTag>
</imageTags>
<!--基础镜像 jdk1.8 -->
<baseImage>java</baseImage>
<maintainer>lcxm xuduochoua@163.com</maintainer>
<!-- 切换到ROOT目录 -->
<workdir>/ROOT</workdir>
<cmd>["java", "-version"]</cmd>
<entryPoint>["java", "-jar", "${project.build.finalName}.jar"]</entryPoint>
<!-- 指定dockerfile路径 -->
<!--
-->
<dockerDirectory>${project.basedir}</dockerDirectory>
<!--指定远程docker api地址 -->
<dockerHost>https://139.129.118.96:2375</dockerHost>
<dockerCertPath>D:\tools\data\docker\ca\</dockerCertPath>
<!--<dockerHost>http://localhost:2375/</dockerHost>-->
<!-- 这里是复制 jar 包到 docker 容器指定目录配置 类似add中的target -->
<resources>
<resource>
<targetPath>/ROOT</targetPath>
<!-- 用于指定需要复制的根目录 ${project.build.directory} 表示target目录-->
<directory>${project.build.directory}</directory>
<!--用于指定需要复制的文件${project.build.finalName}.jar指的是打包后的jar包文件 类似add中的 目标 --> <include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.10</version>
<executions>
<execution>
<id>default</id>
<goals>
<goal>build</goal>
<goal>push</goal>
</goals>
</execution>
</executions>
<configuration>
<repository>139.129.118.96/${project.artifactId}</repository>
<tag>${project.version}</tag>
<buildArgs>
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
<JAR_EXPOSE>8082</JAR_EXPOSE>
</buildArgs>
</configuration>
</plugin>
查看已经开放的端口
firewall-cmd --list-ports
开放端口
firewall-cmd--zone=public --add-port=8080/tcp --permanent
重启防火墙
firewall-cmd --reload
# 停止
firewall systemctl stop firewalld.service
# 禁止开机启动
firewall systemctl disabled1 firewalld.service