Ken的杂谈
  • Ken的杂谈 (current)
  • 关于
  • 杂谈
    Java Spring Spring Boot Spring Cloud MyBatis C# .NET Core .NET ASP.NET Core ASP.NET ClassLibrary Mono 数据库 MySQL SQL Server 网络 缓存 Web Linux CentOS Ubuntu macOS Windows openEuler Nginx ServiceStack JS/JQ 正则 工具 IDE Grafana Exceptions CI/CD Solution 微服务 Arch Docker 杂谈
  • 系列
    Java 快速入门系列教程 Spring Boot 入门教程 Spring Boot 2.x 入门教程 Spring Cloud 入门教程 .NET Core 快速入门教程 ASP.NET Core 2.1 入门教程 CentOS 7 快速上手教程 Ubuntu快速上手入门教程 Hyper-V基础教程 Docker入门教程
  • GitHub

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

Linux Docker @ 2023-02-08 21:52:32 · 阅读:(4271)

一、前言

通常我们的应用都需要对外提供访问,另外也往往不是独立运行的,基本都会使用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保存以下代码

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文件

# 使用官方提供的 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

生成镜像

docker build -t helloworld .

3、运行&测试

创建并运行容器并将本机的9000端口映射到容器端口8000

docker run -d --name myhello -p 9000:8000 helloworld

测试访问

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保存以下代码

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, "\r\nTotal 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文件

# 使用官方提供的 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

生成镜像

docker build -t network_play .

3、运行并连接容器

3.1、创建桥接网络bridge_play

# 创建网络,默认类型为桥接
docker network create bridge_play

# 指定类型创建网络
docker network create -d bridge bridge_play

3.2、创建容器并桥接

docker run -d --name netplay01 -p 9001:8000 --network bridge_play network_play 
docker run -d --name redisplay01 --network bridge_play redis

3.3、查看网络情况

docker network inspect bridge_play

IPAM字段主要展示了网段、网关相关信息

{
    "Driver":"default",
    "Options":{

    },
    "Config":[
        {
            "Subnet":"172.18.0.0/16",
            "Gateway":"172.18.0.1"
        }
    ]
}

Containers字段会展示使用该桥接网络的容器,可以看到netplay01、redisplay01两个容器都接入了bridge_play

{
    "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、解析验证

# 进入容器
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、访问测试

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进行容器编排

Ken的杂谈

本文由 ken.io 创作,采用CC BY 3.0 CN协议 进行许可。 可自由转载、引用、甚至修改,但需署名作者且注明出处。

Linux Docker

随笔目录


    © Copyright 2012-2025 Ken的杂谈

    豫ICP备10025012号

    ASP.NET Core(6.0) on Linux