docker
docker
使用到了容器化技术,相当于虚拟化技术的一个缩影,相当于把一个系统需要的依赖打包成一个容器
镜像: 对于一个系统的描述,可以利用镜像来构建容器,同时也可以通过容器转换为镜像,镜像可以使用 dockerfile
来构建,或者可以从仓库中拉取镜像
docker
的常用命令就不说了...,参考 docker
Dockerfile
Dockerfile
的作用就是通过已经有的镜像构建容器,比如可以构建装go
的ubuntu
系统,就像是可以把所有依赖打包到一个镜像中并且基于这一个镜像构建容器
接下来基于 alpine
系统构建一个 go
的运行环境,alpine
系统是一个 linux
发行版,体积小但是足以满足各种业务需求
首先拉取alpine
系统的镜像:
sudo docker pull alpine
之后构建 Dockerfile
在 alpine
系统中装载go
语言环境,dockerfile
如下:
FROM alpine
# 构建容器中需要运行的命令
RUN mkdir /go && cd /go \
&& wget https://go.dev/dl/go1.24.1.linux-amd64.tar.gz \
&& tar -C /usr/local -zxf go1.24.1.linux-amd64.tar.gz \
&& rm -rf /go/go1.24.1.linux-amd64.tar.gz \
&& mkdir /lib64 \
&& ln -s /bin/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2
# 配置系统环境变量
ENV GOPATH /go
ENV PATH /usr/local/go/bin:$GOPATH/bin:$PATH
# 表示启动时需要运行的命令,防止容器退出
CMD ["ping" , "www.baidu.com"]
之后构建容器:
sudo docker build -t go:alpine .
启动容器
sudo docker run --name go -d go:alpine
进入容器查看是否构建成功
sudo docker exec -it go sh
利用 Docker 部署项目
分为两种方式:
- 构建好
go
语言的容器之后,进行数据卷的映射,并且在容器中运行项目 - 编译好可执行文件,并且基于可执行文件来构建
Docker
镜像并且基于镜像构建容器
利用数据卷挂载的方式
- 首先挂载数据卷:
sudo docker run --name go-zero \
-p 8888:8888 \
-v /home/loser/im-learn/chapter2/grpc-demo1/go-zero:/go/src/im-learn \
-d go:alpine
- 进入容器并且启动项目,注意到可以如果使用
go module
需要配置镜像
sudo docker exec -it go-zero sh
cd /go/src/im-learn/api
go run .
利用 Dockerfile 构建
- 首先编译得到可执行文件:
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o bin/user-api ./user.go
Dockfile
文件如下:
FROM alpine
# 创建目标文件夹,并且复制内容
RUN mkdir /user && mkdir /user/bin && mkdir /user/conf
# 复制宿主机内容到容器中
COPY bin/user-api /user/bin/
# 复制配置文件(其实也可以挂载)
COPY etc/user.yaml /user/conf/
# 提供可执行文件权限
RUN chmod +x /user/bin/user-api
# 指定工作目录
WORKDIR /user
# 设置容器启动命令,使用 ENTRYPOINT 命令,和 CMD 不同的是不可以被替换
ENTRYPOINT ["/user/bin/user-api" , "-f" , "/user/conf/user.yaml"]
注意各种命令的含义,参考: https://www.runoob.com/docker/docker-dockerfile.html
容器网络
docker
安装之后运行的时候会默认创建三个网络,可以使用 docker network ls
查看,内容如下:
NETWORK ID NAME DRIVER SCOPE
00bf102cf338 bridge bridge local
7ad790d33916 host host local
cca9f20e71ae none null local
三种模式的含义如下:
none
模式: 这一中模式下容器会独立network
,并且没有进行任何网络配置,比如分配ip
等bridge
模式:Docker
创建一个虚拟以太网桥docker0
,新的容器自动连接到这一个接口:host
模式: 容器直接使用主机的网络信息
容器网络相关命令
参考 docker
docker 容器互通
- 通过宿主机做桥接(端口映射)
- 容器都位于同一个网络段之下(需要使用
--net
指定网络) - 通过
link
命令(可以通过容器名访问,底层可能使用了DNS
)
docker-compose
docker-compose
类似于一个shell
脚本,作用就是可以根据配置文件的内容运行容器
Target: 启动三个容器分别运行 user-api
, user-rpc
和 etcd
, 并且实现容器之间的互通(使用三者的可执行文件 + Dockerfile
构建镜像)
- 创建一个网络段
user
, 创建命令如下:
sudo docker network create --subnet=168.10.0.0/24 user
- 编写
docker-compose.yaml
文件,内容如下,注意语法(不会就去查就可以了):
version: "3"
services:
# 服务名
etcd:
# 选择镜像:镜像的选择会先从本地找,如果没有会去仓库中拉取下来
image: bitnami/etcd
# 可以选择指定的dockerfile自动帮我构建
build:
# 指定dockerfile所在的目录
context: ./
# 指定dockerfile的文件名
dockerfile: Dockerfile
# 定义创建的容器名
container_name: etcd
# 使创建的容器与宿主机绑定端口
ports:
- "2379:2379"
- "2380:2380"
# 配置系统环境变量
environment:
- ETCD_ENABLE_V2=true
- ALLOW_NONE_AUTHENTICATION=yes
- ETCD_ADVERTISE_CLIENT_URLS=http://etcd:2379
- ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379
- ETCD_NAME=etcd
# 配置容器与宿主机的共享目录
# 同时需要注意宿主机存在目录,并且要基于权限不然系统会直接报错
volumes:
- ./data:/bitnami/etcd/data
- ./logs:/bitnami/etcd/logs
# 设置容器的网络段
networks:
user:
ipv4_address: 168.10.0.20
user-rpc:
image: user-rpc:alpine
container_name: user-rpc
ports:
- "8080:8080"
# 与etcd服务互通
links:
- etcd
# 需要等指定容器启动后才可以启动,填写的是容器的服务名
depends_on:
- etcd
networks:
user:
user-api:
image: user-api:alpine
container_name: user-api
ports:
- "8888:8888"
# 与etcd服务互通
links:
- etcd
# 需要等指定容器启动后才可以启动,填写的是容器的服务名
depends_on:
- etcd
- user-rpc
networks:
user:
# 由docker创建
networks:
user:
external:
name: user
- 使用如下命令构建即可:
sudo docker-compose up -d
- 可以使用如下命令停止并且删除容器:
sudo docker-compose down