Docker入门:端口映射与容器互联

2023-04-07 15:46:33 浏览数 (1)

一、前言

通常我们的应用都需要对外提供访问,另外也往往不是独立运行的,基本都会使用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进行容器编排

0 人点赞