Docker
1. 自定义镜像
前面我们都是使用docker pull
拉取仓库中现成的镜像,但是如果我们想要将一个Java应用程序构建成镜像然后部署应该怎么做呢?这个时候我们就需要自定义镜像了
**镜像:**本质上就是一堆文件的集合,包含了应用程序本身以及它运行时所需要的系统函数库、环境、配置、应用程序。
**自定义镜像步骤:**1、准备Linux运行环境 => 2、安装Java运行环境 => 3、拷贝jar包 => 4、配置启动脚本
但是需要注意的是:镜像文件不是无序随意摆放的,构建文件之间存在依赖关系,因此需要有结构的组织在一起,镜像可以看做是由多个Layer(层)构成的,最底层的就是BaseImage(基础镜像)通常是模拟Linux环境的镜像,最上层的就是Entrypoint(入口),通常是应用程序启动脚本。
而构建镜像我们只需要借助Dockerfile文件即可,该文件就是用来描述构建镜像的结构与步骤的,我们只需要了解如何编写Dockerfile,然后使用命令:docker build
就可以构建镜像了。
Dockerfile语法:
只有了解Dockerfile的语法我们才可以编写出Dockerfile文件:
指令 | 说明 | 示例 |
---|---|---|
FROM | 指定基础镜像 | FROM centos:6 |
ENV | 设置环境变量 | ENV key value |
COPY | 拷贝本地文件到镜像目录中 | COPY ./xx.jar /tmp/app.jar |
RUN | 执行Linux shell脚本 | RUN yum install -y gcc |
EXPOSE | 指定运行时监听端口 | EXPOSE 8080 |
EXTRYPOINT | 应用启动脚本 | ENTRYPOINT java -jar xx.jar |
例如:要基于Ubuntu镜像构建一个Java应用,Dockerfile如下所示:
# 指定基础镜像
FROM ubuntu:16.04
# 配置环境变量,JDK的安装目录、容器内时区
ENV JAVA_DIR=/usr/local
ENV TZ=Asia/Shanghai
# 拷贝jdk和java项目的包
COPY ./jdk8.tar.gz $JAVA_DIR/
COPY ./docker-demo.jar /tmp/app.jar
# 设定时区
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 安装JDK
RUN cd $JAVA_DIR \
&& tar -xf ./jdk8.tar.gz \
&& mv ./jdk1.8.0_144 ./java8
# 配置环境变量
ENV JAVA_HOME=$JAVA_DIR/java8
ENV PATH=$PATH:$JAVA_HOME/bin
# 指定项目监听的端口
EXPOSE 8080
# 入口,java项目的启动命令
ENTRYPOINT ["java", "-jar", "/app.jar"]
但是还是太麻烦了,毕竟我们每次部署Java应用都需要准备好Linux环境以及JDK运行环境,因此大佬也准备好了JDK的基础镜像,因此上述Dockerfile可以简化为如下Dockerfile:
# 基础镜像
FROM openjdk:11.0-jre-buster
# 设定时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 拷贝jar包
COPY docker-demo.jar /app.jar
# 入口
ENTRYPOINT ["java", "-jar", "/app.jar"]
接下来我们准备好程序jar包就可以来构建java镜像了:
执行命令:docker build -t myimage .
- -t:指定构建的镜像名称(不能包含大写字母)
- . 表示Dockerfile所在目录
此时镜像已经创建完毕,我们尝试创建并运行该容器:
docker run -d \
--name hm \
-p 8080:8080 \
myimage
2. 网络
我们已经创建完了一个Java项目的容器,而Java项目通常需要访问其他中间件比如MySQL、Redis、ES等等,我们的容器能否互连呢?
使用命令:docker inspect hm / nginx
发现两个容器的IP地址分别为:172.17.0.2
以及172.17.0.3
说明在同一网段中,接下来使用命令:docker exec -it hm bash
进入容器,尝试ping nginx所在IP
但是此处容器的IP并不是固定的,比如我先启动nginx,然后再启动hm,此时IP地址就会发生变化,但是我们Java项目配置中间件连接地址必须是固定的,因此Docker提供了** 网络**,常见命令有:
命令 | 说明 |
---|---|
docker network create | 创建一个网络 |
docker network ls | 查看所有网络 |
docker network rm | 删除某个网络 |
docker network connect | 使指定容器加入网络 |
docker network disconnect | 使指定容器离开网络 |
docker network inspect | 查看网络具体信息 |
最重要的是,如果我们在自定义网络(默认网络不行)中,可以让处于同一个网络的多个容器通过容器名称进行访问!!!
下面我们就来尝试重新创建并运行容器并指定网络:
[root@VM-16-5-opencloudos heima-demo]# docker network create hmall
2702b65a783ca46b6a77f197d7ccfe8ab22914d97fa5d8f7acd5cce0818e8971
[root@VM-16-5-opencloudos heima-demo]# docker network ls
NETWORK ID NAME DRIVER SCOPE
05b67283cbd7 bridge bridge local
2b819e8b339d hm-net bridge local
2702b65a783c hmall bridge local
6184100a188f host host local
03009a872cf1 none null local
[root@VM-16-5-opencloudos heima-demo]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@VM-16-5-opencloudos heima-demo]# docker run -d --name hm -p 8080:8080 --network hmall myimage
a6b1de8b0ff6a269cd0472f9202af0381609e672d3dbc8b3bb443098a3d2305e
[root@VM-16-5-opencloudos heima-demo]# docker run -d --name nginx -p 80:80 --network hmall nginx
df88a660872488114dbadb5f8fce176038e66359727096c59aeb70bbfcef250f
[root@VM-16-5-opencloudos heima-demo]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
df88a6608724 nginx "/docker-entrypoint.…" 3 seconds ago Up 2 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp nginx
a6b1de8b0ff6 myimage "java -jar /app.jar" 28 seconds ago Up 27 seconds 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp hm
[root@VM-16-5-opencloudos ~]# docker exec -it hm bash
root@a6b1de8b0ff6:/# ping nginx
PING nginx (172.19.0.3) 56(84) bytes of data.
64 bytes from nginx.hmall (172.19.0.3): icmp_seq=1 ttl=64 time=0.103 ms
64 bytes from nginx.hmall (172.19.0.3): icmp_seq=2 ttl=64 time=0.065 ms
此时我们已经实现了基于容器名称实现互连