Docker 镜像构建与容器网络配置
Docker 镜像构建与容器网络配置详解
自定义 Java 项目镜像制作及容器间网络通信
1. 镜像构建基础
1.1 镜像结构
- 镜像能实现跨操作系统快速部署应用,核心在于包含程序运行所需的系统函数库、环境、配置、依赖等所有必要文件。
- 自定义镜像的本质是按顺序准备程序运行的基础环境、依赖、应用本身、运行配置等文件并打包。例如部署 Java 应用的镜像,对应步骤为:
- 准备 Linux 基础运行环境(无需完整操作系统,仅需基础运行环境)
- 安装并配置 JDK
- 拷贝 Jar 包
- 配置启动脚本
- 镜像文件按操作步骤分层叠加(Layer),每一层形成的文件单独打包并标记唯一 ID。若构建时某些层已存在,可直接复用,无需重复制作。例如 Linux 运行环境通用性强,Docker 官方已提供相关基础镜像,构建 Java 镜像时可直接使用。
1.2 Dockerfile
- Dockerfile 是记录镜像结构和构建过程的文件,使用固定语法描述每一层的操作,Docker 可依据其自动打包镜像。官方文档参考:https://docs.docker.com/engine/reference/builder/
- 常用指令及说明:
| 指令 | 说明 | 示例 |
|---|---|---|
| FROM | 指定基础镜像 | FROM centos:6 |
| ENV | 设置环境变量,可在后续指令中使用 | ENV key value |
| COPY | 拷贝本地文件到镜像的指定目录 | COPY ./xx.jar /tmp/app.jar |
| RUN | 执行 Linux 的 shell 命令,通常用于安装过程 | RUN yum install gcc |
| EXPOSE | 指定容器运行时监听的端口,用于提示镜像使用者 | EXPOSE 8080 |
| ENTRYPOINT | 镜像中应用的启动命令,容器运行时会调用 | ENTRYPOINT java -jar xx.jar |
基于 Ubuntu 镜像构建 Java 应用的 Dockerfile 示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21# 指定基础镜像
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"]优化后的 Dockerfile(利用包含 JDK 的基础镜像,省去 JDK 配置步骤):
1
2
3
4
5
6
7
8
9# 基础镜像
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"]
1.3 构建镜像
准备工作:将项目的 jar 包(如 docker-demo.jar)和 Dockerfile 拷贝到虚拟机的指定目录(如 /root/demo)。
构建命令:
1
2
3
4
5
6# 进入镜像目录
cd /root/demo
# 开始构建,-t指定镜像名称(repository和tag),.表示Dockerfile所在路径
docker build -t docker-demo:1.0 .
# 也可直接指定Dockerfile目录
docker build -t docker-demo:1.0 /root/demo查看构建的镜像:
docker images,示例结果:1
2
3
4REPOSITORY TAG IMAGE ID CREATED SIZE
docker-demo 1.0 d6ab0b9e64b9 27 minutes ago 327MB
nginx latest 605c77e624dd 16 months ago 141MB
mysql latest 3218b38490ce 17 months ago 516MB运行镜像:
1
2
3
4
5
6
7
8# 创建并运行容器
docker run -d --name dd -p 8080:8080 docker-demo:1.0
# 查看容器
docker ps(可简写为dps)
# 示例结果
CONTAINER ID IMAGE PORTS STATUS NAMES
78a000447b49 docker-demo:1.0 0.0.0.0:8080->8080/tcp, :::8090->8090/tcp Up 2 seconds dd
f63cfead8502 mysql 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp Up 2 hours mysql访问容器应用:
curl localhost:8080/hello/count,示例结果:<h5>欢迎访问黑马商城, 这是您第1次访问<h5>
2. Docker 网络配置
2.1 容器网络互联测试
查看容器 IP:通过
docker inspect 容器名或docker inspect --format='{{range .NetworkSettings.Networks}}{{println .IPAddress}}{{end}}' 容器名查看,例如查看 MySQL 容器 IP:1
2docker inspect --format='{{range .NetworkSettings.Networks}}{{println .IPAddress}}{{end}}' mysql
# 可能得到IP:172.17.0.2测试网络连通性:进入某一容器(如 dd 容器),通过
ping 目标容器IP测试,示例:1
2
3
4
5
6
7# 进入dd容器
docker exec -it dd bash
# 测试与MySQL容器的连通性
ping 172.17.0.2
# 示例结果(可连通)
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.053 ms问题:容器虚拟 IP 不固定,若开发时写死 IP,部署时可能因 IP 变化导致连接失败。
2.2 常用网络命令
| 命令 | 说明 | 文档地址 |
|---|---|---|
| docker network create | 创建一个网络 | docker network create |
| docker network ls | 查看所有网络 | docker network ls |
| docker network rm | 删除指定网络 | docker network rm |
| docker network prune | 清除未使用的网络 | docker network prune |
| docker network connect | 使指定容器加入某网络 | docker network connect |
| docker network disconnect | 使指定容器离开某网络 | docker network disconnect |
| docker network inspect | 查看网络详细信息 | docker network inspect |
2.3 自定义网络配置示例
创建自定义网络:
1
docker network create hmall
查看网络:
1
2
3
4
5
6
7docker network ls
# 示例结果
NETWORK ID NAME DRIVER SCOPE
639bc44d0a87 bridge bridge local
403f16ec62a2 hmall bridge local
0dc0f72a0fbb host host local
cd8d3e8df47b none null local让容器加入网络并设置别名(同一网络内的容器可通过别名互相访问):
1
2
3
4# 让mysql容器加入hmall网络,别名为db(容器默认别名是容器名)
docker network connect hmall mysql --alias db
# 让dd容器(Java项目)加入hmall网络
docker network connect hmall dd测试别名访问:
1
2
3
4
5
6
7
8
9
10
11
12# 进入dd容器
docker exec -it dd bash
# 用db别名访问mysql容器
ping db
# 示例结果
PING db (172.18.0.2) 56(84) bytes of data.
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=1 ttl=64 time=0.070 ms
# 用容器名访问mysql容器
ping mysql
# 示例结果
PING mysql (172.18.0.2) 56(84) bytes of data.
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=1 ttl=64 time=0.044 ms
2.4 网络配置总结
- 在自定义网络中,容器可拥有多个别名,默认别名为容器名本身。
- 同一自定义网络中的容器,可通过别名互相访问,无需依赖固定 IP,解决了 IP 不固定导致的连接问题。
-
感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 Gavin的博客