一、DockerFile
DockerFile简介
Docker是用来构建Docker镜像文件,由一条条docker指令和参数构成的脚本。
DockerFile构建过程
小总结
从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段,
Dockerfile是软件的原材料
Docker镜像是软件的交付品
Docker容器则可以认为是软件镜像的运行态,也即依照镜像运行的容器实例
Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。
1 Dockerfile,需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;
2 Docker镜像,在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行 Docker镜像时会真正开始提供服务;
3 Docker容器,容器是直接提供服务的
docker保留字
vim Dockerfile FROM centos MAINTAINER zzyy<zzyybs@126.com> ENV MYPATH /usr/local WORKDIR $MYPATH #安装vim编辑器 RUN yum -y install vim #安装ifconfig命令查看网络IP RUN yum -y install net-tools #安装java8及lib库 RUN yum -y install glibc.i686 RUN mkdir /usr/local/java #ADD 是相对路径jar,把jdk-8u171-linux-x64.tar.gz添加到容器中,安装包必须要和Dockerfile文件在同一位置 ADD jdk-8u171-linux-x64.tar.gz /usr/local/java/ #配置java环境变量 ENV JAVA_HOME /usr/local/java/jdk1.8.0_171 ENV JRE_HOME $JAVA_HOME/jre ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH ENV PATH $JAVA_HOME/bin:$PATH EXPOSE 80 CMD echo $MYPATH CMD echo "success--------------ok" CMD /bin/bash docker run -it 新镜像名字:TAG .(当前目录) docker run -it centosjava8:1.5 /bin/bash
虚悬镜像
虚悬镜像:仓库名、标签名都是 的镜像,称为 dangling images(虚悬镜像)。
在构建或者删除镜像时可能由于一些错误导致出现虚悬镜像。
列出docker中的虚悬镜像:
docker image ls -f dangling=true
虚悬镜像一般是因为一些错误而出现的,没有存在价值,可以删除:
# 删除所有的虚悬镜像 docker image prune
Docker发布微服务
搭建一个简单的SpringBoot项目:
1、 创建maven工程,pom为:
<?xml version="1.0" encoding="UTF-8"?> <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> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.6</version> </parent> <groupId>org.study</groupId> <artifactId>test-docker</artifactId> <packaging>pom</packaging> <version>1.0-SNAPSHOT</version> <modules> <module>docker_boot</module> </modules> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> </project>
2、 新建Module,pom为:
<?xml version="1.0" encoding="UTF-8"?> <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"> <parent> <artifactId>test-docker</artifactId> <groupId>org.study</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>docker_boot</artifactId> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
3、编写一个配置文件
server: port: 6001
4、 编写主启动类
package com.study; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * @author tengyer 2022/05/06 16:34 */ @SpringBootApplication public class DockerBootApplication { public static void main(String[] args) { SpringApplication.run(DockerBootApplication.class, args); } }
5、 编写一个Controller
package com.study.controller; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import java.util.UUID; /** * @author tengyer 2022/05/06 16:35 */ @RestController public class OrderController { @Value("${server.port}") private String port; @RequestMapping("/order/docker") public String helloDocker() { return "hello world \t" + port + "\t" + UUID.randomUUID().toString(); } @RequestMapping(value = "/order/index", method = RequestMethod.GET) public String index() { return "服务端口号:" + "\t" + port + "\t" + UUID.randomUUID().toString(); } }
在Idea中运行没有问题时,将其使用maven的package打成jar包。
发布微服务项目到Docker容器
将项目jar包上传到服务器
编写Dockerfile
FROM openjdk:8-oracle MAINTAINER lee # 在主机 /var/lib/docker目录下创建一个临时文件,并链接到容器的 /tmp VOLUME /tmp # 将jar包添加到容器中,并命名为 springboot_docker.jar ADD docker_boot-1.0-SNAPSHOT.jar /springboot_docker.jar # 运行jar包 RUN bash -c 'touch /springboot_docker.jar' ENTRYPOINT ["java", "-jar", "/springboot_docker.jar"] # SpringBoot项目配置的端口号为6001,需要将6001暴露出去 EXPOSE 6001
3、构建镜像
docker build -t springboot_docker:1.0 .
4、 启动容器:
docker run -d -p 6001:6001 --name springboot springboot_docker:1.0
二、Docker网络
简介
docker安装并启动服务后,会在宿主机中添加一个虚拟网卡。
在Docker服务启动前,使用 ifconfig 或 ip addr 查看网卡信息:
● ens33或eth0:本机网卡
● lo:本机回环网络网卡
● 可能有virbr0(CentOS安装时如果选择的有相关虚拟化服务,就会多一个以网桥连接的私网地址的virbr0网卡,作用是为连接虚拟网卡提供NAT访问外网的功能。如果要移除该服务,可以使用 yum remove libvirt-libs.x86_64)
使用 systemctl start docker启动Docker服务后,会多出一个 docker0 网卡。
作用:
● 容器间的互联和通信以及端口映射
● 容器IP变动时候可以通过服务名直接网络通信而不受到影响
Docker容器的网络隔离,是通过Linux内核特性 namespace和 cgroup 实现的。
Docker网络命令
查看Docker网络模式:
docker network ls
添加Docker网络:
docker network create xxx
删除Docker网络:
docker network rm xxx
查看网络元数据:
docker network inspect xxx
删除所有无效的网络:
docker network prune
能干嘛
docker网络模式
查看某个容器的网络模式:
# 通过inspect获取容器信息,最后20行即为容器的网络模式信息 docker inspect 容器ID | tail -n 20
bridge模式
Docker 服务默认会创建一个 docker0 网桥(其上有一个 docker0 内部接口),该桥接网络的名称为docker0,它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。Docker 默认指定了 docker0 接口 的 IP 地址和子网掩码,让主机和容器之间可以通过网桥相互通信。
docker0上面的每个veth匹配某个容器实例内部的eth0,两两配对,一一匹配。
host模式
直接使用宿主机的 IP 地址与外界进行通信,不再需要额外进行 NAT 转换。
如果在 docker run 命令中同时使用了 --network host 和 -p端口映射,例如:
docker run -p 8082:8080 --network host tomcat
那么会出现一个警告:
WARNING: Published ports are discarded when using host network mode
因为此时已经使用了host模式,本身就是直接使用的宿主机的IP和端口,此时的-p端口映射就没有了意义,也不会生效,端口号还是会以主机端口号为主。
正确做法是:不再进行-p端口映射,或者改用bridge模式
container模式
新建的容器和已经存在的一个容器共享网络IP配置,而不是和宿主机共享。
新创建的容器不会创建自己的网卡、IP,而是和一个指定的容器共享IP、端口范围。两个容器除了网络共享,其他的如文件系统、进程列表依然是隔离的。
docker run -it --name alpine1 alpine /bin/sh # 指定和 alpine1 容器共享网络 docker run -it --netrowk container:alpine1 --name alpine2 alpine /bin/sh
此时使用 ip addr查看两台容器的网络,会发现两台容器的eth0网卡内的IP等信息完全相同。
如果关掉了alpine1容器,因为alpine2的网络使用的alpine1共享网络,所以关掉alpin1后,alpine2的eth0网卡也随之消失了。
自定义网络
容器间的互联和通信以及端口映射。
容器 IP 变动时候可以通过服务名直接网络通信而不受影响。(类似Eureka,通过服务名直接互相通信,而不是写死IP地址)。
自定义桥接网络(自定义网络默认使用的是桥接网络 bridge):
1、 新建自定义网络
docker network create tomcat_network
2、 查看网络列表
docker network ls
3、 创建容器时,指定加入我们自定义的网络中
docker run -d -p 8081:8080 --network tomcat_network --name tomcat1 tomcat:8.5-jdk8-corretto docker run -d -p 8082:8080 --network tomcat_network --name tomcat2 tomcat:8.5-jdk8-corretto
4、此时进入tomcat1中,使用ping命令测试连接tomcat2容器名,发现可以正常连通
# 安装ifconfig命令 yum install -y net-tools # 安装ip addr命令 yum install -y iproute # 安装ping命令 yum install -y iputils # 直接ping容器名,不需要ping IP地址 ping tomcat2
三、Docker-compose容器编排
简介
Docker-Compose 是 Docker 官方的开源项目,负责实现对Docker容器集群的快速编排。
Docker-Compose可以管理多个Docker容器组成一个应用。需要定义一个yaml格式的配置文件 docker-compose.yml,配置好多个容器之间的调用关系,然后只需要一个命令就能同时启动/关闭这些容器。
下载
curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose docker-compose --version
compose编排实例
示例:
# docker-compose文件版本号 version: "3" # 配置各个容器服务 services: microService: image: springboot_docker:1.0 container_name: ms01 # 容器名称,如果不指定,会生成一个服务名加上前缀的容器名 ports: - "6001:6001" volumes: - /app/microService:/data networks: - springboot_network depends_on: # 配置该容器服务所依赖的容器服务 - redis - mysql redis: image: redis:6.0.8 ports: - "6379:6379" volumes: - /app/redis/redis.conf:/etc/redis/redis.conf - /app/redis/data:data networks: - springboot_network command: redis-server /etc/redis/redis.conf mysql: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: '123456' MYSQL_ALLOW_EMPTY_PASSWORD: 'no' MYSQL_DATABASE: 'db_springboot' MYSQL_USER: 'springboot' MYSQL_PASSWORD: 'springboot' ports: - "3306:3306" volumes: - /app/mysql/db:/var/lib/mysql - /app/mysql/conf/my.cnf:/etc/my.cnf - /app/mysql/init:/docker-entrypoint-initdb.d networks: - springboot_network command: --default-authentication-plugin=mysql_native_password # 解决外部无法访问 networks: # 创建 springboot_network 网桥网络 springboot_network:
编写完成docker-compose.yml后,进行语法检查:
# 进行语法检查
docker-compose config -q
如果语法检查没有任何问题,进行创建、启动:
docker-compose up -d