一、前言
通常我们的应用都需要对外提供访问,另外也往往不是独立运行的,基本都会使用MySQL、Redis等数据库存储数据,并且应用之间也会存在互相访问的情况,本文主要介绍容器端口的开放与绑定,以及基于Docker Network的容器互联
1、本文主要内容
- 使用Golang构建HTTP Server,并使用Redis进行访问计数
- Docker 镜像开放端口及端口映射
- Docker Network介绍及使用
- 基于Docker Network实现容器互联
2、本文环境信息
环境 | 说明 |
---|---|
Docker | Docker CE 20.10.22 |
Docker Desktop | 4.16 |
Docker Redis镜像 | 7.0.x |
Docker Golang镜像 | 1.20 |
Golang | 1.20 |
Windows | Windows 11 |
curl for Windows | 7.87 |
二、外部访问容器
我们可以在制作Docker镜像时通过EXPOSE参数开放指定端口,然后使用docker run命令创建容器时可以通过-P参数指定容器内外网络映射
1、代码准备
用golang写的一个简单http server,监听8000端口,默认输出helloworld,新建helloworld.go保存以下代码
代码语言:javascript复制package main
import (
"fmt"
"log"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
log.Println("request:", r.Host, r.URL)
fmt.Fprintf(w, "Hello, World! ---ken.io")
}
func main() {
http.HandleFunc("/", handler)
log.Println("starting server on port 8000")
log.Fatal(http.ListenAndServe(":8000", nil))
}
2、制作镜像
编写Dockerfile文件
代码语言:javascript复制# 使用官方提供的 Go 镜像作为基础镜像
FROM golang:1.20
# 将工作目录设置为 /app
WORKDIR /app
# 将helloworld.go复制到 /app 下
COPY helloworld.go /app
# 允许宿主机访问容器的 8000 端口
EXPOSE 8000
# 设置容器进程为:go run helloworld.go
CMD go run helloworld.go
生成镜像
代码语言:javascript复制docker build -t helloworld .
3、运行&测试
创建并运行容器并将本机的9000端口映射到容器端口8000
代码语言:javascript复制docker run -d --name myhello -p 9000:8000 helloworld
测试访问
代码语言:javascript复制curl localhost:9000
# 输出示例
Hello, World! ---ken.io
三、容器互联
Docker提供了网络模块,可以方便地创建、管理虚拟网络,以实现容器与宿主机,以及容器跟容器之间的网络通信,Docker network提供了bridge、host、overlay、ipvlan、macvlan、none共6种网络类型,其中常用的就是bridge、host两种网络类型
bridge(桥接):桥接就是常见的局域网组网方式,用于容器跟容器之间的通信,也是默认网络类型
host(宿主机):去掉容器和Docker宿主机之间的网络隔离,直接使用宿主机的网络,只能创建1个
1、代码准备
用golang写的一个简单http server,监听8000端口,对访问的请求通过Redis进行计数,RedisHost命名为:redisplay01,后续需要在桥接网络下创建同名的Redis容器使用
新建network_play.go保存以下代码
代码语言:javascript复制package main
import (
"fmt"
"github.com/go-redis/redis"
"log"
"net/http"
)
var cache = redis.NewClient(&redis.Options{
Addr: "redisplay01:6379",
})
func handler(w http.ResponseWriter, r *http.Request) {
log.Println("request:", r.Host, r.URL)
fmt.Fprintf(w, "Hello, Wordl! ---docker network play by ken.io")
fmt.Fprintf(w, "rnTotal view:%s", cache.Incr("count"))
}
func main() {
http.HandleFunc("/", handler)
log.Println("starting server on port 8000")
log.Fatal(http.ListenAndServe(":8000", nil))
}
2、制作镜像
编写Dockerfile文件
代码语言:javascript复制# 使用官方提供的 Go 镜像作为基础镜像
FROM golang:1.20
# 将工作目录设置为 /app
WORKDIR /app
# 将network_play.go复制到 /app 下
COPY network_play.go /app
# 导入依赖的Redis go module
RUN go mod init network_play
RUN go get github.com/go-redis/redis
# 允许宿主机访问容器的 8000 端口
EXPOSE 8000
# 设置容器进程为:go run network_play.go
CMD go run network_play.go
生成镜像
代码语言:javascript复制docker build -t network_play .
3、运行并连接容器
3.1、创建桥接网络bridge_play
代码语言:javascript复制# 创建网络,默认类型为桥接
docker network create bridge_play
# 指定类型创建网络
docker network create -d bridge bridge_play
3.2、创建容器并桥接
代码语言:javascript复制docker run -d --name netplay01 -p 9001:8000 --network bridge_play network_play
docker run -d --name redisplay01 --network bridge_play redis
3.3、查看网络情况
代码语言:javascript复制docker network inspect bridge_play
IPAM字段主要展示了网段、网关相关信息
代码语言:javascript复制{
"Driver":"default",
"Options":{
},
"Config":[
{
"Subnet":"172.18.0.0/16",
"Gateway":"172.18.0.1"
}
]
}
Containers字段会展示使用该桥接网络的容器,可以看到netplay01、redisplay01两个容器都接入了bridge_play
代码语言:javascript复制{
"541753509fb681aa19a88fc5accb56930727e5a17e28cf8061ba0e0f6682c4c0":{
"Name":"netplay01",
"EndpointID":"f6f000ecc2a45ba1a9a8c460ca26ea278cbcf5677b179949ea99084a14e657a8",
"MacAddress":"02:42:ac:12:00:02",
"IPv4Address":"172.18.0.2/16",
"IPv6Address":""
},
"893c00b5e8b13b468a991cb9694d9a36601daab01996dcc804ed62cc89832990":{
"Name":"redisplay01",
"EndpointID":"cfe45f6c022a0f9f4d5f7157675114cc9c1f771888028e08a466e97eaeae071f",
"MacAddress":"02:42:ac:12:00:03",
"IPv4Address":"172.18.0.3/16",
"IPv6Address":""
}
}
3.4、解析验证
代码语言:javascript复制# 进入容器
docker exec -it netplay01 /bin/bash
# 安装依赖
apt-get update -y
apt-get install -y iputils-ping
# ping测试
ping redisplay01
# 输出示例
PING redisplay01 (172.18.0.3) 56(84) bytes of data.
64 bytes from redisplay01.bridge_play (172.18.0.3): icmp_seq=1 ttl=64 time=0.666 ms
64 bytes from redisplay01.bridge_play (172.18.0.3): icmp_seq=2 ttl=64 time=0.443 ms
64 bytes from redisplay01.bridge_play (172.18.0.3): icmp_seq=3 ttl=64 time=0.213 ms
64 bytes from redisplay01.bridge_play (172.18.0.3): icmp_seq=4 ttl=64 time=0.254 ms
3.5、访问测试
代码语言:javascript复制curl localhost:9001
# 输出示例
Hello, Wordl! ---docker network play by ken.io
Total view:incr count: 11
四、备注
1、Docker Network常用命令
命令 | 说明 | 语法 |
---|---|---|
connect | 将指定容器连接到指定网络 | docker network connect {network name} {container name} |
create | 创建网络 | docker network create {network name} |
disconnect | 断开指定容器与指定网络的连接 | docker network disconnect {network name} {container name} |
inspect | 显示一个或多个网络的详细信息 | docker network inspect {network name} |
ls | 列出所有网络 | docker network ls |
prune | 删除所有未使用的网络 | docker network prune |
rm | 删除一个或多个网络 | docker network rm {network name} {network name} …… |
2、相关阅读
https://docs.docker.com/network/
https://docs.docker.com/engine/reference/commandline/network/
- 系列名称:Docker入门教程
- 上一篇:Docker入门:使用数据卷、文件挂载进行数据存储与共享
- 下一篇:Docker入门:使用Docker Compose进行容器编排