栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

Docker入门到放弃

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Docker入门到放弃

一、安装docker 1.安装 (1)卸载之前的docker
yum remove docker 
                  docker-client 
                  docker-client-latest 
                  docker-common 
                  docker-latest 
                  docker-latest-logrotate 
                  docker-logrotate 
                  docker-engine
(2)安装docker的依赖
yum install -y yum-utils 
    device-mapper-persistent-data 
    lvm2
(3)设置docker仓库
yum-config-manager 
      --add-repo 
      https://download.docker.com/linux/centos/docker-ce.repo
(4)安装docker
yum install -y docker-ce docker-ce-cli containerd.io
(5)启动docker
systemctl start docker
(6)设置开机启动
systemctl enable docker
(7)测试是否安装成功,拉取一个hello-world镜像
docker pull hello-world
docker run hello-world
# 可以看到有以下输出
Hello from Docker!
2.配置加速器 (1)配置阿里云镜像加速器

阿里云控制台搜索 容器镜像服务

找到 镜像加速器,根据右边的命令进行操作

在centos操作以下命令

# 1.创建文件夹
mkdir -p /etc/docker
# 2.写daemon.json文件
tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://dokomztn.mirror.aliyuncs.com"]
}
EOF
# 3.重新加载上面的配置文件
systemctl daemon-reload
# 4.重启docker
systemctl restart docker
二、Docker基本操作 1.镜像操作 (1)拉取镜像
# 默认拉取dockerhub上面的最新版本
docker pull tomcat
# 拉取指定版本的镜像
docker pull tomcat:8
(2)查看所有镜像
docker images
(3)删除某一个镜像
 # 根据镜像id删除,二选一即可
 docker image rm imageid
 docker rmi -f imageid
 # 根据镜像名称删除,二选一即可
 docker image rm 镜像名称
 docker rmi -f 镜像名称
 # 镜像后面可以通过 `:版本`,删除指定版本的,例如:
 docker rmi -f hello-world:latest
(4)删除所有镜像
# 如果该镜像有运行中的容器,需要先停止基于该镜像创建的容器,否则删除会有问题
docker rmi -f $(docker image ls)
2.容器操作 (1)查看所有运行中的容器
docker ps
(2)查看所有的容器,包含非运行的
docker ps -a
(3)根据镜像创建容器
# 以tomcat为例,-d表示后台运行,--name为容器指定名称,-p表示将容器的端口映射到宿主主机的端口
docker run -d --name my-tomcat01 -p 9090:8080 tomcat
(4)进入到某一个容器
# my-tomcat01为容器名称,也可以是容器的id
docker exec -it my-tomcat01 /bin/bash
(5)查看容器使用情况
docker stats
(6)查看容器日志
docker logs 容器名称/容器id
(7)查看容器使用情况
docker inspect 容器名称/id
(8)停止/启动容器
docker start 容器名称/容器id
docker stop 容器名称/容器id
(9)删除某一个容器
# 删除之前需要先停止该容器
docker rm 容器名称/容器id
(10)删除所有容器
# 不需要停止即可删除
docker rm -f $(docker ps -aq)
3.安装tomcat (1)指定拉取版本8的tomcat
docker pull tomcat:8
(2)启动tomcat容器
# 创建成功之后浏览器访问宿主主机ip加端口号9090即可
docker run -d --name my-tomcat-01 -p 9090:8080 tomcat
(3)tomcat启动完成之后访问404的问题
# 1.进入到tomcat的容器中
docker exec -it xxx /bin/bash
# 进入到webapps,查看是否有文件
cd webapps
# 如果没有的话就会出现404的问题,此时删除webapps文件夹,复制webapps.dist到webapps
rm -rf webapps
cp -r webapps.dist/. webapps
# 重新访问即可

docker network ls 查看网路类型,有bridge、host、none三种类型

docker inspect bridge查看网卡

找到tomcat容器所对应的ip地址,一般都是以172.17.0.x的,比如是172.17.0.3

在centos里面通过 curl http://172.17.0.3:9090 也可以访问到tomcat

4.安装mysql (1)拉取mysql镜像
docker pull mysql
(2)创建mysql容器
# -e指定参数,docker中为mysql指定密码的参数为 `MYSQL_ROOT_PASSWORD`,
# --privileged使容器内的root用户拥有真正的root权限
docker run -d --name mysql01 -p 3301:3306 -e MYSQL_ROOT_PASSWORD=123456 --privileged mysql
(3)连接不上报 client does not support support authentication protocol requested by server…
# 重新修改root的密码和连接地址
alter user 'root'@'%' identified with mysql_native_password by '123456';
# 刷新
flush privileges;
三、Dockerfile

docker镜像库的github地址:https://github.com/docker-library

1.根据 Dockerfile生成image镜像 (1)这里以mysql为例,从docker-library找到mysql的Dockerfile文件,直接复制一份

(2)然后 linux创建一个文件夹 mysql-image
mkdir mysql-image
(3)进入到该文件夹里面,创建 Dockerfile 文件,
vi Dockerfile
(4)把上面的从docker-library复制的文件粘贴到这里的Dockerfile里面,然后保存退出
# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh"
#
# PLEASE DO NOT EDIT IT DIRECTLY.
#

FROM debian:buster-slim

# add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added
RUN groupadd -r mysql && useradd -r -g mysql mysql

RUN apt-get update && apt-get install -y --no-install-recommends gnupg dirmngr && rm -rf /var/lib/apt/lists/*

# add gosu for easy step-down from root
# https://github.com/tianon/gosu/releases
ENV GOSU_VERSION 1.14
RUN set -eux; 
	savedAptMark="$(apt-mark showmanual)"; 
	apt-get update; 
	apt-get install -y --no-install-recommends ca-certificates wget; 
	rm -rf /var/lib/apt/lists/*; 
	dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; 
	wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; 
	wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; 
	export GNUPGHOME="$(mktemp -d)"; 
	gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; 
	gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; 
	gpgconf --kill all; 
	rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; 
	apt-mark auto '.*' > /dev/null; 
	[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; 
	apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; 
	chmod +x /usr/local/bin/gosu; 
	gosu --version; 
	gosu nobody true

RUN mkdir /docker-entrypoint-initdb.d

RUN set -eux; 
	apt-get update; 
	apt-get install -y --no-install-recommends 
		openssl 
# FATAL ERROR: please install the following Perl modules before executing /usr/local/mysql/scripts/mysql_install_db:
# File::Basename
# File::Copy
# Sys::Hostname
# Data::Dumper
		perl 
		xz-utils 
		zstd 
	; 
	rm -rf /var/lib/apt/lists/*

RUN set -eux; 
# gpg: key 3A79BD29: public key "MySQL Release Engineering " imported
	key='859BE8D7C586F538430B19C2467B942D3A79BD29'; 
	export GNUPGHOME="$(mktemp -d)"; 
	gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; 
	mkdir -p /etc/apt/keyrings; 
	gpg --batch --export "$key" > /etc/apt/keyrings/mysql.gpg; 
	gpgconf --kill all; 
	rm -rf "$GNUPGHOME"

ENV MYSQL_MAJOR 5.7
ENV MYSQL_VERSION 5.7.38-1debian10

RUN echo 'deb [ signed-by=/etc/apt/keyrings/mysql.gpg ] http://repo.mysql.com/apt/debian/ buster mysql-5.7' > /etc/apt/sources.list.d/mysql.list

# the "/var/lib/mysql" stuff here is because the mysql-server postinst doesn't have an explicit way to disable the mysql_install_db codepath besides having a database already "configured" (ie, stuff in /var/lib/mysql/mysql)
# also, we set debconf keys to make APT a little quieter
RUN { 
		echo mysql-community-server mysql-community-server/data-dir select ''; 
		echo mysql-community-server mysql-community-server/root-pass password ''; 
		echo mysql-community-server mysql-community-server/re-root-pass password ''; 
		echo mysql-community-server mysql-community-server/remove-test-db select false; 
	} | debconf-set-selections 
	&& apt-get update 
	&& apt-get install -y 
		mysql-server="${MYSQL_VERSION}" 
# comment out a few problematic configuration values
	&& find /etc/mysql/ -name '*.cnf' -print0 
		| xargs -0 grep -lZE '^(bind-address|log)' 
		| xargs -rt -0 sed -Ei 's/^(bind-address|log)/#&/' 
# don't reverse lookup hostnames, they are usually another container
	&& echo '[mysqld]nskip-host-cachenskip-name-resolve' > /etc/mysql/conf.d/docker.cnf 
	&& rm -rf /var/lib/apt/lists/* 
	&& rm -rf /var/lib/mysql && mkdir -p /var/lib/mysql /var/run/mysqld 
	&& chown -R mysql:mysql /var/lib/mysql /var/run/mysqld 
# ensure that /var/run/mysqld (used for socket and lock files) is writable regardless of the UID our mysqld instance ends up having at runtime
	&& chmod 1777 /var/run/mysqld /var/lib/mysql

VOLUME /var/lib/mysql

COPY docker-entrypoint.sh /usr/local/bin/
RUN ln -s usr/local/bin/docker-entrypoint.sh /entrypoint.sh # backwards compat
ENTRYPOINT ["docker-entrypoint.sh"]

EXPOSE 3306 33060
CMD ["mysqld"]
(5)保存退出
:wq
(6)根据Dockerfile文件生成一个镜像
docker build -t mysql-image .
2.Dockerfile语法
# 指定基础镜像
FROM debian:buster-slim
# 运行
RUN groupadd -r mysql && useradd -r -g mysql mysql
# 设置变量的值,ENV MYSQL_MAJOR 5.7,可以通过docker run --e key=value修改,后面可以直接使用${MYSQL_MAJOR}
ENV MYSQL_MAJOR 5.7
# 设置镜像标签
LABEL
# 镜像的作者信息,即也就是Author
MAINTAINER tianqingzhao
# 数据存储在哪一个目录
VOLUME /var/lib/mysql
#将主机的文件复制到镜像内,如果目录不存在,会自动创建所需要的目录,注意只是复制,不会提取和解压
COPY docker-entrypoint.sh /usr/local/bin/
# 将主机的文件复制到镜像内,和COPY类似,只是ADD会对压缩文件提取和解压
ADD application.yml /etc/itcrazy2016/
# 指定镜像要暴露的端口,启动镜像时,可以使用-p将该端口映射给宿主机
EXPOSE 3306 33060
# 和CMD的使用类似
ENTRYPOINT ["docker-entrypoint.sh"]
3.Dockerfile入门 (1)编写springboot工程,添加maven依赖
 	
        org.springframework.boot
        spring-boot-starter-parent
        2.2.0.RELEASE
         
    
    com.gupao
    dockerfile-demo
    0.0.1-SNAPSHOT
    dockerfile-demo
    Demo project for Spring Boot

    
        1.8
    

    
        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
            
                
                    org.junit.vintage
                    junit-vintage-engine
                
            
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    
(2)提供一个接口
@SpringBootApplication
public class DockerfileDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DockerfileDemoApplication.class, args);
    }
    
    @RestController
    public class DockerController {
        
        @GetMapping("/dockerfile")
        @ResponseBody
        String dockerfile(@RequestParam(defaultValue = "hello docker") String str) {
            return str;
        }
    }
}
(3)自己编写一个Dockerfile文件
FROM openjdk:8
# 指定维护人
MAINTAINER tianqingzhao
# 指定镜像名称、版本、作者
LABEL name=“dockerfile-demo” version="1.0" author="tianqingzhao"
# 把centos的jar包拷贝到镜像里面
COPY dockerfile-demo-0.0.1-SNAPSHOT.jar springboot-dockerfile-demo.jar
# 执行该命令启动
CMD ["java", "-jar", "springboot-dockerfile-demo.jar"]
(4)构建镜像
docker build -t springboot-dockerfile-demo .
(5)创建容器
docker run -d --name springboot-dockerfile-demo springboot-dockerfile-demo
(6)查看日志
docker logs springboot-dockerfile-demo
(7)进入容器内访问
docker exec -it springboot-dockerfile-demo /bin/bash
(8)请求jar包的接口接口访问成功
curl http://localhost:8080/dockerfile
(9)将该容器的端口映射到centos上面,宿主主机的浏览器也可以访问
# 启动完成之后可以在我们的浏览器访问映射到centos的地址,centosip:8888/dockerfile
docker run -d --name springboot-dockerfile-demo02 -p 8888:8080 springboot-dockerfile-demo
四、Docker hub仓库 1.官方的Docker hub

dockerhub仓库地址:https://hub.docker.com

(1)首先注册账号和密码,注册完之后在centos登录
# centos通过 `docker login` 命令登录,账号和密码输入我们在 https://hub.docker.com 注册的
docker login --username=账号  https://hub.docker.com
# 给之前的sprinboot应用的镜像重新打一个标签(相当于拷贝一个副本)
docker tag springboot-dockerfile-demo:latest tianqingzhao/springboot-dockerfile-demo-hub:v1.0
# 推送到hub仓库
docker push tianqingzhao/springboot-dockerfile-demo-hub:v1.0
(2)等待推送完成,在dockerhub仓库就可以看到我们的镜像了

(3)推送完成之后,删除本地的镜像,从dockerhub里面拉取一下
# 先删除本地之前打好的标签
docker rmi -f tianqingzhao/springboot-dockerfile-demo:v1.0
# 拉取dockerhub仓库的
docker pull tianqingzhao/springboot-dockerfile-demo:v1.0
# 创建容器运行并访问
docker run -d --name springboot-dockerfile-demo-hub -p 8811:8080 tianqingzhao/springboot-dockerfile-demo:v1.0
# 外部浏览器访问也能成功
http://192.168.0.136:8811/dockerfile
2.阿里云Docker hub (1)在 容器镜像服务 里面点击实例列表,然后创建个人版实例

(2)然后创建命名空间 qztian,创建完成之后设置仓库类型为公有

(3)创建完成之后在centos登录阿里云进行推送
# 在centos登录阿里云,这里推送到哪个地区,推送成功之后就在阿里云控制台就选择哪一个地区查看,例如我这里推送到beijing,推送成功之后就选择北京
docker login --username=tianqingzhao registry.cn-beijing.aliyuncs.com
# 给springboot应用的image重新打一个标签(相当于拷贝一个副本)
docker tag 镜像名称 registry.cn-beijing.aliyuncs.com/阿里云命名空间名称/推送到阿里云镜像名称:版本号
# 比如我上面创建的命名空间名称为 qztian
docker tag springboot-dockerfile-demo registry.cn-beijing.aliyuncs.com/qztian/springboot-dockerfile-demo-aliyun:v1.0
# 推送到阿里云仓库
docker push registry.cn-beijing.aliyuncs.com/qztian/springboot-dockerfile-demo-aliyun:v1.0
(4)推送成功之后,选择我们推送的北京地区,就可以看到我们的镜像了

(5)从阿里云镜像仓库拉取我们推送的
# 同样先删除本地的
docker rmi -f registry.cn-beijing.aliyuncs.com/qztian/springboot-dockerfile-demo-aliyun:v1.0
# 拉取阿里云仓库
docker pull registry.cn-beijing.aliyuncs.com/qztian/springboot-dockerfile-demo-aliyun:v1.0
# 创建该镜像的容器,端口号映射到centos为8899,
docker run -d --name springboot-dockerfile-demo-aliyun -p 8899:8080 registry.cn-beijing.aliyuncs.com/qztian/springboot-dockerfile-demo-aliyun:v1.0
# 然后访问外部浏览器也能成功
http://192.168.0.136:8899/dockerfile
3.搭建自己的Docker harbor (1)harbor基于docker-compose启动的,所以需要先安装docker-compose
# 下载 Docker-Compose版本,使用daocloud下载
curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
# 将可执行权限应用于二进制文件:
chmod +x /usr/local/bin/docker-compose
# 创建软链
ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
# 验证是否安装成功
docker-compose --version
(2)下载harbor压缩包

github仓库地址:https://github.com/goharbor/harbor

下载harbor安装包,地址:https://github.com/goharbor/harbor/releases?page=1

(3)下载完成之后解压,更改 harbor.yml 文件配置
# 连接地址
hostname: centos的ip
# 密码
harbor_admin_password: Harbor123456
(4)配置harbor的镜像地址
# 编辑/etc/docker/daemon.json文件
vi /etc/docker/daemon.json
# 加上该配置
"insecure-registries":["192.168.0.136:80"]
# 加完之后,配置harbor的ip以及端口,默认端口号80
{
  "registry-mirrors": ["https://dokomztn.mirror.aliyuncs.com"],
  "insecure-registries":["192.168.0.136:80"]
}

(5)启动harbor
./install.sh
(6)停止和启动
# 停止Harbor
docker-compose down -v
# 启动Harbor
docker-compose up -d
(7)推送一个镜像到Harbor,同阿里云镜像一样,这里先要新建一个项目

(8)新建好之后在centos登录harbor并复制镜像
# 登录harbor地址,然后输入密码显示登录成功即可
docker login -u admin 192.168.0.136:80
# 给springboot应用打一个标签。这里复制出来的镜像以ip:port/项目名称/镜像名称:版本号
docker tag springboot-dockerfile-demo:latest 192.168.0.136:80/qztian/springboot-dockerfile-demo-harbor:v1.0
# 推送
docker push 192.168.0.136:80/qztian/springboot-dockerfile-demo-harbor:v1.0
(9)推送完成之后进入到该项目即可看到

(10)推送完成之后同样拉取一把
# 拉取之前先删除本地之前打好的标签的镜像
docker rmi -f 192.168.0.136:80/qztian/springboot-dockerfile-demo-harbor:v1.0
# 从harbor上面拉取
docker pull 192.168.0.136:80/qztian/springboot-dockerfile-demo-harbor:v1.0
# 创建容器运行
docker run -d --name springboot-dockerfile-demo-harbor -p 8866:8080 192.168.0.136:80/qztian/springboot-dockerfile-demo-harbor:v1.0
# 外部浏览器访问该springboot应用的接口即可成功
http://192.168.0.136:8866/dockerfile
五、根据container创建出image (1)拉取centos镜像
docker pull centos
(2)创建centos容器
# 加上-it是希望交互式启动,否则会停止
docker run -d -it --name my-centos centos:latest
(3)进入到该容器
docker exec -it my-centos /bin/bash

查看vim命令是否有,没有的话进行安装

yum install vim

安装 vim 命令的时候可能会如下错误:

Error: Failed to download metadata for repo 'appstream': Cannot prepare internal mirrorlist: No URLs

这是因为CentOS 官方在2020 年 12 月 8 号宣布了停止维护 CentOS Linux 的计划,并推出了 CentOS Stream 项目,CentOS Linux 8 作为 RHEL 8 的复刻版本,生命周期缩短,于 2021 年 12 月 31 日停止更新并停止维护(EOL),更多的信息可以查看 CentOS 官方公告。如果需要更新 CentOS,需要将镜像从 mirror.centos.org 更改为 vault.centos.org,参考文章:https://blog.csdn.net/weixin_43252521/article/details/124409151

# 分别执行以下命令解决上面报错问题
cd /etc/yum.repos.d/
sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
yum makecache
yum update -y
yum -y install vim
(4)生成一个带 vim命令的centos的image
docker commit my-centos vim-centos-image

创建容器

docker run -d -it --name my-vim-centos vim-centos-image

进入容器查看是否有vim命令

docker exec -it my-vim-centos /bin/bash
# 输入vim命令验证

使用commit生成的镜像不显示过程,使用Dockerfile生成的会显示每一步执行的过程,官网推荐的也是Dockerfile

六、container资源管理 1.启动一个tomcat,任何参数不配置分配默认的参数
docker run -d --name tomcat01 -p 8811:8080 tomcat:8
# 查看状态
docker stats tomcat01
# 会显示一下内容
CONTAINER ID   NAME       CPU %     MEM USAGE / LIMIT     MEM %     NET I/O     BLOCK I/O   PIDS
258dd43c4d61   tomcat01   0.13%     60.45MiB / 2.709GiB   2.18%     656B / 0B   0B / 0B     25
2.使用命令监控
# 配置内容大小和cpu权重
docker run -d --name tomcat02 --memory 100M --cpu-shares 10 -p 8822:8080 tomcat:8 
# 查看状态
docker stats tomcat02
# 回显示一下内容
CONTAINER ID   NAME       CPU %     MEM USAGE / LIMIT   MEM %     NET I/O     BLOCK I/O   PIDS
ea61e5ea38e1   tomcat02   0.12%     45.02MiB / 100MiB   45.02%    656B / 0B   0B / 0B     18
3.可视化监控工具

github地址:https://github.com/weaveworks/scope

(1)快速开始
# 1.下载
curl -L git.io/scope -o /usr/local/bin/scope
# 上面如果报  Failed to connect to 2001::6817:7dbd: Network is unreachable 错误,就使用这条命令下载
curl -L https://github.com/weaveworks/scope/releases/download/latest_release/scope -o /usr/local/bin/scope

# 2.授权
chmod a+x /usr/local/bin/scope
# 3.启动
scope launch centos的ip
(2)启动成功之后就可以通过浏览器访问管理界面了,默认端口号4040


点击其中一个container可以查看使用情况

也可以点击image进行查看创建的container,感兴趣的自行研究

七、网络 1.在 centos创建network namespace (1) 创建ns1
# 创建network namespace,添加网络命名空间名称为 ns1
ip netns add ns1
# 查看网络命名空间名称
ip netns list

# 查看添加的网络命名空间
ip netns exec ns1 ip link show
# 显示以下内容
1: lo:  mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    
# 启动该网络命名空间
ip netns exec ns1 ifup lo

# 再次查看
ip netns exec ns1 ip link show
# 显示一下内容
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    
# 查看物理主机
ip link show
# 显示以下其中一条内容
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    
# 发现添加的网络命名空间和物理主机的网络命名空间都为 UNKNOWN
(2)按照以上步骤创建ns2
ip netns add ns2
# 查看网络命名空间名称
ip netns list

# 查看添加的网络命名空间
ip netns exec ns2 ip link show
# 显示以下内容
1: lo:  mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    
# 启动该网络命名空间
ip netns exec ns2 ifup lo

接下来使这两个网络命名空间进行通信

2.veth pair:Virtual Ethernet Pair

成对出现的网卡,创建出来是默认能够联通的,也就是使ns1和ns2联通

(1)创建veth网卡
# 创建两个网卡并使它们连接
ip link add veth-ns1 type veth peer name veth-ns2
# 再次查看
ip link show
# 发现它们两个已经连上了
52: veth-ns2@veth-ns1:  mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 7a:70:ac:99:cc:60 brd ff:ff:ff:ff:ff:ff
53: veth-ns1@veth-ns2:  mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether fe:5d:55:36:01:94 brd ff:ff:ff:ff:ff:ff
(2)把这两个派给ns1和ns2这两个网络命名空间
# 把网卡veth-ns1派给网络命名空间ns1
ip link set veth-ns1 netns ns1
# 派送完成之后通过 ip link show再次查看已经看不到veth-ns1这个网卡了
# 再次查看ns1这个网络命名空间
ip netns exec ns1 ip link show
# 显示一下内容,说明veth-ns1这个网卡已经被派送过来了
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
53: veth-ns1@if52:  mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether fe:5d:55:36:01:94 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    
# 同样给ns2派送网卡veth-ns2
ip link set veth-ns2 netns ns2
# 再次查看ns2这个网络命名空间
ip netns exec ns2 ip link show
# 显示一下内容表示派送成功
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
52: veth-ns2@if53:  mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 7a:70:ac:99:cc:60 brd ff:ff:ff:ff:ff:ff link-netnsid 0
(3)给这两个网卡添加ip地址
# 给ns1这个网络命名空间的veth-ns1网卡添加ip为192.168.0.11,子网掩码为24,
ip netns exec ns1 ip addr add 192.168.0.11/24 dev veth-ns1
# 启动该网络命名空间
ip netns exec ns1 ip link set veth-ns1 up
# 再次查看
ip netns exec ns1 ip a

# 操作ns2这个网络命名空间
ip netns exec ns2 ip addr add 192.168.0.12/24 dev veth-ns2
# 启动该网络命名空间
ip netns exec ns2 ip link set veth-ns2 up
# 查看该网络命名空间
ip netns exec ns2 ip a
(4)验证两个网络命名空间是否互通
# 在ns1上面去ping ns2
ip netns exec ns1 ping 192.168.0.12
# 在ns2上面去ping ns1
ip netns exec ns2 ping 192.168.0.11

看到以下表示ping通

(5)启动两个tomcat容器,并进入容器进行查看ip去验证是否能互相ping通

ip a查看网络,如果报bash: ip: command not found错误,使用以下命令安装ip命令

apt update && apt install -y iproute2

进入其中一个,然后ping另外一个的ip,如果ping命令失败,使用以下命令安装ping命令

# 更新
apt-get update
# 安装
apt install iputils-ping
3.安装查看网桥工具 (1)安装
yum install bridge-utils
# 查看
brctl show
# 会显示以下内容
bridge name			bridge id			STP enabled				interfaces
br-57f9401a93d6		8000.0242814bbbac	no		
docker0				8000.0242603a900c	no						veth57d3d66
																veth6f9793a
                                                                veth7f8cf69
                                                                vethd979e57

(2)在centos通过ip a再次查看网络,可以找到 brctl show 命令出现的docker0的网卡信息
41: veth57d3d66@if40:  mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 92:8c:21:a1:c4:ea brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::908c:21ff:fea1:c4ea/64 scope link 
       valid_lft forever preferred_lft forever
43: veth7f8cf69@if42:  mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 96:5c:08:88:07:82 brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet6 fe80::945c:8ff:fe88:782/64 scope link 
       valid_lft forever preferred_lft forever
47: veth6f9793a@if46:  mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 7a:05:4e:b2:7b:a6 brd ff:ff:ff:ff:ff:ff link-netnsid 2
    inet6 fe80::7805:4eff:feb2:7ba6/64 scope link 
       valid_lft forever preferred_lft forever
49: vethd979e57@if48:  mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether ce:0a:83:9c:a3:ef brd ff:ff:ff:ff:ff:ff link-netnsid 3
    inet6 fe80::cc0a:83ff:fe9c:a3ef/64 scope link 
       valid_lft forever preferred_lft forever
(3)原理图

4.网络类型 (1)查看docker网络类型
# 查看
docekr network ls
# 显示一下内容
57f9401a93d6   harbor_harbor   bridge    local
6b5feb06c2bf   host            host      local
cd6aba8f33fa   none            null      local
# docker中创建的任何容器都是基于bridge网络类型的,
# host是和宿主主机一样的网络

# 查看bridge类型的
docker network inspect bridge
(2)给docker 创建网络
# 创建一个网络,默认为bridge类型的
docker network create tomcat-net
# 再次查看已经出现了
docker network ls
# 查看创建出来的tomcat-net网络信息,它的网段已经不是172.17了,而是172.19或者其他递增的
docker network inspect tomcat-net

# 创建网络并指定网段
docker network create --subnet=172.19.0.0/24 tomcat-net
# 删除网络
docker network rm tomcat-net
(3)创建容器并指定网络
docker run -d --name custom-net-tomcat --network tomcat-net tomcat
# 再来查看该容器的网络
docker exec -it custom-net-tomcat ip a
# 可以发现它就是刚刚创建的172.19开头的网段了

# 这时候用创建出来的网络去ping之前的tomcat是ping不同的
docker exec -it custom-net-tomcat ping 172.17.0.2
# 因为现在的custom-net-tomcat这个容器是新的网络,跟之前docker默认的不一样

用下面一张图来理解

接下来把tomcat01添加到tomcat-net里面

docker network connect tomcat-net tomcat01
# 添加完再次查看
docker network inspect tomcat-net
# 此时已经能看到tomcat01被添加到tomcat-net这个网络里面了

# 再去查看tomcat01这个容器的网络
docker inspect tomcat01 
# 此时也能看到tomcat-net这个网络了

这时候进入custom-tomcat-net这个容器里面去ping一下tomcat01这个容器,此时已经可以ping通了。

docker exec -it custom-tomcat-net /bin/bash
ping 172.17.0.2

用下面一张图来理解一下

5.用容器名称对外提供连接

直接使用容器名称去ping两个容器的话是ping不同的,分别给他们指定网络之后可以ping通。

(1)指定网络可以ping通

创建两个tomcat容器,并分别指定网络为上面创建的tomcat-net,此时再去根据容器名称ping的话是可以ping通的。

# 这这两个容器都指定网络为tomcat-net
docker network connect tomcat-net tomcat01
docker network connect tomcat-net tomcat02
# 再去ping
docker exec -it tomcat01 ping tomcat02
(2)通过 --link 参数
# 指定tomcat01容器连接到tomcat02上面,通过dns连接
docker run -d --name tomcat01 --link tomcat02 tomcat:8
# 再次去ping可以ping通
docker exec -it tomcat01 ping tomcat02

生产中推荐使用自定义网络来进行连接。

6.解决多机网络通信问题

overlay网络模式,实现的是vxlan

八、Docker数据持久化 1.Volume
# 查看所有的volume
docker volume ls
# 查看某一个volume详情
docker volume inspect VOLUMENAME
# 删除某一个volume
docker vlume rm VOLUMENAME
(1)以mysql为例来说明
# 拉取mysql镜像
docker pull mysql
# 创建mysql01容器
docker run -d --name mysql01 -e MYSQL_ROOT_PASSWORD=123456 mysql
# 进入到mysql01容器
docker exec -it mysql01 /bin/bash
# 在容器里面进入到/var/lib/mysql目录
cd /var/lib/mysql
# 可以看到有以下文件
'#ib_16384_0.dblwr'  '#innodb_temp'   binlog.000001   binlog.index   ca.pem	       client-key.pem   ib_logfile0   ibdata1   mysql	    performance_schema	 public_key.pem    server-key.pem   undo_001
'#ib_16384_1.dblwr'   auto.cnf	      binlog.000002   ca-key.pem     client-cert.pem   ib_buffer_pool   ib_logfile1   ibtmp1    mysql.ibd   private_key.pem	 server-cert.pem   sys		    undo_002

# 退出容器,在centos里面查看数据持久化
# 首选查看刚创建出来的msql01的VOLUME NAME
docker volume ls
# 然后根据VOLUME NAME的值查看该volume数据存储的位置
docker volume inspect 6a19afe432358b32607297e828150308440976509b0e19b48616a60cdfd7ab7e
# 可以看到该容器的数据是存储在/var/lib/docker/volumes下面的,
[
    {
        "CreatedAt": "2022-05-18T01:18:31Z",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/6a19afe432358b32607297e828150308440976509b0e19b48616a60cdfd7ab7e/_data",
        "Name": "6a19afe432358b32607297e828150308440976509b0e19b48616a60cdfd7ab7e",
        "Options": null,
        "Scope": "local"
    }
]
# 进入到该完整目录里面,可以看到有以下文件,和在容器中查看的一样
auto.cnf       binlog.000002  ca-key.pem  client-cert.pem  #ib_16384_0.dblwr  ib_buffer_pool  ib_logfile0  ibtmp1        mysql      performance_schema  public_key.pem   server-key.pem  undo_001
binlog.000001  binlog.index   ca.pem      client-key.pem   #ib_16384_1.dblwr  ibdata1         ib_logfile1  #innodb_temp  mysql.ibd  private_key.pem     server-cert.pem  sys             undo_002


# 每次创建容器都会在centos的机器上面生成一个文件夹,用来保存数据
(2)给创建的容器指定volume名称
# 指定volume名称,并指定容器内存储数据目录
docker run -d --name mysql02 -v mysql02_volume:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql
# 再次查看
docker volume ls
# 就显示我们指定的
local     mysql02_volume

# 删除容器之后,centos查看volume还会存在,也就是容器被删除之后,可以恢复数据,除非把centos的volume给删除了那就无法恢复

# 在mysql02这个容器中的数据存储目录里面创建一个文件,centos也会同步显示
docker exec -it mysql02 /bin/bash
cd /var/lib/mysql
touch test.txt
# 查看已经能显示了
ls
# 退出容器
exit
# 在centos查看该容器对应的volume所在的路径
docker volume inspect mysql02_volume
# 查看该volume所在的路径,也已经能看到 test.txt 文件了
ls /var/lib/docker/volumes/mysql02_volume/_data
(3)删除mysql02容器,并进行恢复
# 首先在该容器创建一个数据库
create database tqz_test;
# 查看该数据库已经被创建出来了
show databases;

# 删除
docker rm -f mysql02
# 再重新创建一个容器,并指定volume
docker run -d --name mysql02 -v mysql02_valume:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql
# 进入到该容器查看
docker exec -it test-mysql /bin/bash
mysql -u root -p
show databases;
# 可以发现上面创建的tqz_test数据库还存在
2.Bind mounts
# 在centos创建一个文件夹
mkdir /usr/local/malls
# 编辑一个html页面
vi test.html
# 随便写上一段内容
Hello Bind mounts!

# 创建一个tomcat01的容器,并且指定挂载centos的项目,也就是上面我们创建的页面挂载上去
docker run -d --name tomcat01 -p 9090:8080 -v /usr/local/malls/:/usr/local/tomcat/webapps/malls tomcat
# 进入容器中里面,可以在tomcat的webapps目录下面看到该项目
docker exec -it tomcat01 /bin/bash
# 浏览器访问可以看到我们test.html页面的内容
http://192.168.0.136:9090/malls/test.html
九、搭建mysql高可用集群 1.Percona Xtradb Cluster 搭建集群

hub.docker.com搜索:percona/percona-xtradb-cluster

# 拉取pxc镜像
docker pull percona/percona-xtradb-cluster:5.7.21
# 由于镜像名称太长,给其打个tag重新起个名字
docker tag percona/percona-xtradb-cluster:5.7.21 pxc
# 删除之前的镜像
docker rmi percona/percona-xtradb-cluster:5.7.21

创建pxc-net网络

# 创建网络并指定网段
docker network create --subnet=172.20.0.0/24 pxc-net
# 查看网络详情
docker network inspect pxc-net 

创建三个volume,分别给三个mysql容器使用

docker volume create --name v1
docker volume create --name v2
docker volume create --name v3

创建三个mysql容器

# 创建mysql01容器,映射到centos端口为3301,指定volume为v1,在容器中的存储路径为/var/lib/mysql,mysql密码为123456,集群名称为PXC,集群之间同步数据的密码为123456,指定容器的网络为pxc-net,指定ip为172.20.0.2
docker run -d --name=mysql01 -p 3301:3306 -v v1:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=123456 --privileged --net=pxc-net --ip 172.20.0.2 pxc

# 创建mysql02容器,映射到centos端口为3302,指定volume为v2,加入到mysql01里面组成集群,指定ip为172.20.0.3
docker run -d --name=mysql02 -p 3302:3306 -v v2:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=123456 -e CLUSTER_JOIN=mysql01 --privileged --net=pxc-net --ip 172.20.0.3 pxc

# 创建mysql03容器,映射到centos端口为3303,指定volume为v3,加入到mysql01里面组成集群,指定ip为172.20.0.4
docker run -d --name=mysql03 -p 3303:3306 -v v3:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=123456 -e CLUSTER_JOIN=mysql01 --privileged --net=pxc-net --ip 172.20.0.4 pxc

通过客户端工具分别连接到三个mysql,在其中一个mysql里面创建数据库,然后创建一张表并添加数据,其他两个mysql里面也能同步到数据。

2.Haproxy 负载均衡
# 拉取haproxy镜像
docker pull haproxy
# 在centos机器创建一个文件夹
mkdir -p /usr/local/haproxy
# 在上面的目录下创建一个haproxy.cfg配置文件
touch /usr/local/haproxy.haproxy.cfg

以下为 haproxy.cfg 配置文件内容

global
	#工作目录,这边要和创建容器指定的目录对应,haproxy容器的目录默认在该路径
	# chroot /usr/local/etc/haproxy
	#日志文件
	log 127.0.0.1 local5 info
	#守护进程运行
	daemon
defaults
	log global
	mode http
	#日志格式
	option httplog
	#日志中不记录负载均衡的心跳检测记录
	option dontlognull
	#连接超时(毫秒)
	timeout connect 5000
	#客户端超时(毫秒)
	timeout client 50000
	#服务器超时(毫秒)
	timeout server 50000
	#监控界面
	listen admin_stats
	#监控界面的访问的IP和端口
	bind 0.0.0.0:8123
	#访问协议
	mode http
	#控制台URI相对地址
	stats uri /haproxy
	#统计报告格式
	stats realm Global statistics
	#控制台登陆帐户信息
	stats auth admin:admin
	#数据库负载均衡
	listen proxy-mysql
	#访问的IP和端口,haproxy开发的端口为3306
	#假如有人访问haproxy的3306端口,则将请求转发给下面的数据库实例
	bind 0.0.0.0:3306
	#网络协议
	mode tcp
	#负载均衡算法(轮询算法)
	#轮询算法:roundrobin
	#权重算法:static-rr
	#最少连接算法:leastconn
	#请求源IP算法:source
	balance roundrobin
	#日志格式
	option tcplog
	#在MySQL中创建一个没有权限的haproxy用户,密码为空。
	#Haproxy使用这个账户对MySQL数据库心跳检测
	option mysql-check user haproxy
	#以下为三台mysql容器ip和端口号
	server MySQL_1 172.20.0.2:3306 check weight 1 maxconn 2000
	server MySQL_2 172.20.0.3:3306 check weight 1 maxconn 2000
	server MySQL_3 172.20.0.4:3306 check weight 1 maxconn 2000
	#使用keepalive检测死链
	option tcpka

创建haproxy容器

docker run -it -d -p 8123:8123 -p 3306:3306 -v /usr/local/haproxy/:/usr/local/etc/haproxy --name haproxy --privileged --net=pxc-net haproxy

启动完之后浏览器访问

# centos的ip加映射到centos的端口号,后面的uri就是我们再haproxy.cfg配置的stats uri
# 账户和密码使我们在haproxy.cfg配置的stats auth后面的参数
http://192.168.0.136:8123/haproxy 


navicat连接数据库,需要创建一个haproxy用户,在mysql01的容器上面执行以下命令

# 进入mysql01容器
docker exec -it mysql01 /bin/bash
# 进入mysql,并输入密码
mysql -u root -p
# 首选执行该命令,正常情况都可以成功
CREATE USER 'haproxy'@'%' IDENTIFIED BY '';

# 如果创建失败,可以先输入一下命令
drop user 'haproxy'@'%';
flush privileges;
CREATE USER 'haproxy'@'%' IDENTIFIED BY '';
3.springboot项目连接高可用数据库

网络还是使用上面mysql高可用集群和haproxy的网络 pxc-net

上传springboot-mybatis.jar包

注意配置文件

# 数据源
spring:
  datasource:
    # 这里先使用haproxy容器的ip
    url: jdbc:mysql://172.20.0.2:3306/sbm-ds?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

# mybatis托管mapper文件
mybatis:
  mapper-locations: classpath:mapper/*.xml

接口

@RestController
@RequestMapping(value = "/user")
public class UserController {
    
    @Autowired
    private UserService userService;
    
    private AtomicInteger value = new AtomicInteger(0);
    
    // 查询所有用户接口
    @RequestMapping("/getList")
    public R> getList(HttpServletRequest request) {
        String msg = "第 " + value.incrementAndGet() + " 次调用...";
        System.out.println(msg);
        
        List users = userService.getList();
        
        return new R<>(200, msg, users);
    }
    
    // 添加用户接口
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public String add(User user) {
        int result = userService.insertUser(user);
        if (result >= 1) {
            return "添加成功";
        } else {
            return "添加失败";
        }
    }
}

编写 Dockerfile 文件

FROM openjdk:8-jre-alpine
MAINTAINER tianqingzhao
LABEL name="springboot-mybatis" version="1.0" author="tianqingzhao"
COPY springboot-mybatis-0.0.1-SNAPSHOT.jar springboot-mybatis.jar
CMD ["java","-jar","springboot-mybatis.jar"]

基于springboot的jar包和 Dockerfile 文件构建 springboot-mybatis-image 镜像

docker build -t springboot-mybatis-image .

基于image创建容器

# 映射到centos端口号为8811,使用pxc-net的网络,容器的ip使用172.20.0.11
docker run -d --name sbm01 -p 8811:8080 --net=pxc-net --ip 172.20.0.11 springboot-mybatis-image

访问接口

# centos通过curl命令
curl http://localhost:8811/user/getList
4.通过nginx负载均衡访问项目,数据库访问haproxy容器名称

整体流程:用户请求 —》 nginx —》springboot-mybatis容器项目

先删除之前的springboot-mybatis-image镜像和启动的sbm01容器

# 删除镜像
docker rmi springboot-mybatis-image:latest
# 删除容器
docker rm -f sbm01

修改配置文件数据库url连接

# 数据源
spring:
  datasource:
    ### 在同一个网络中,bridge  pxc-net   容器之间不仅可以通过ip访问,而且可以通过名称
    url: jdbc:mysql://haproxy/sbm-ds?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

# mybatis托管mapper文件
mybatis:
  mapper-locations: classpath:mapper/*.xml

打包上传重新构建image,上传之前,先删掉之前传的jar包。基于新上传的jar包重新构建镜像,Dockerfile 文件不用修改。

# 构建新的镜像
docker build -t springboot-mybatis-image .
# 重新构建之后的镜像目前已推送到hub.docker.com仓库,通过以下命令可拉取
docker pull tianqingzhao/springboot-mybatis:v1.0

基于springboot-mybatis-image镜像启动三个容器

# 启动sbm01容器
docker run -d --name sbm01 -p 8811:8080 --net=pxc-net --ip 172.20.0.11 springboot-mybatis-image
# 启动sbm02容器,注意修改容器名称、端口号、ip
docker run -d --name sbm02 -p 8822:8080 --net=pxc-net --ip 172.20.0.12 springboot-mybatis-image
# 启动sbm03容器,注意修改容器名称、端口号、ip
docker run -d --name sbm03 -p 8833:8080 --net=pxc-net --ip 172.20.0.13 springboot-mybatis-image

拉取nginx镜像

docker pull nginx

编写 nginx.conf 配置文件

user nginx;
worker_processes 1;
events {
	worker_connections 1024;
}
http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    sendfile on;
    keepalive_timeout 65;
    
    server {
        listen 80;
        # 访问路径为根路径
        location / {
            proxy_pass http://balance;
        }
    }
    
    upstream balance{
    server 172.18.0.20:8080;
    server 172.18.0.20:8080;
    server 172.18.0.20:8080;
    }
    include /etc/nginx/conf.d/*.conf;
}

创建nginx容器

# 容器名称为nginx,映射到centos端口号为80,把centos机器的nginx.conf挂载到容器的/etc/nginx/nginx.conf目录里面
# 使用pxc-net这个网络,ip为172.20.0.10
docker run -d --name nginx -p 80:80 -v /usr/local/nginx-image/nginx.conf:/etc/nginx/nginx.conf --network=pxc-net --ip 172.20.0.10 nginx

浏览器访问

# 该ip为centosip,由于nginx配置的为根路径,,端口号监听的80,所以直接访问ip加接口即可
http://192.168.0.136/user/getList
# 可以通过docker logs 容器名称 命令查看每个容器输出情况来验证是否做到了负载均衡
十、Docker-compose 1.基于Dockerfile启动一个python应用

在centos机器上面创建一个文件夹,用于存放Dockerfile和python应用的代码

# 创建文件夹
mkdir -p /usr/local/python
# 进入到该文件夹
cd /usr/local/python

接下来在上面创建的文件夹写一个python应用接口,文件名称定义为 app.py

import time

import redis
from flask import Flask

app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)

def get_hit_count():
    retries = 5
    while True:
        try:
            return cache.incr('hits')
        except redis.exceptions.ConnectionError as exc:
            if retries == 0:
                raise exc
            retries -= 1
            time.sleep(0.5)

@app.route('/')
def hello():
    count = get_hit_count()
    return 'Hello World! I have been seen {} times.n'.format(count)

继续在上面的文件夹创建 requirements.txt 文件,该文件用于标识python应用的依赖包

flask
redis

编写 Dockerfile 文件

FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP app.py
ENV FLASK_RUN_HOST 0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY . .
CMD ["flask", "run"]

根据上面的 Dockefile 文件生成镜像

docker build -t python-app-image .

拉取一个轻量级的redis镜像

docker pull redis:alpine

创建网络

# 指定网段为172.17.21.0,名称为python-net
docker network create --subnet=172.21.0.0/24 python-net

基于上面构建的镜像创建容器

docker run -d --name python-app -p 5000:5000 --network python-net python-app-image

基于redis镜像创建容器

docker run -d --name redis -p 6379:6379 --network python-net redis:alpine

浏览器访问

# centos的ip加python应用的端口号
http://192.168.0.136:5000/
# 可以看到有输出,每次访问都会递增1
Hello World! I have been seen 1 times.
2.docker-compose实现上面python应用

删除上面的容器、镜像、网络

docker rm -f python-app
docker rmi -f python-app-image
docker rm -f redis
docker rmi -f redis:alpine
docker network rm python-net

docker-compose是在单机上面进行多个容器的管理部署

首先安装docker-compose

# 下载 Docker-Compose版本,使用daocloud下载
curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
# 将可执行权限应用于二进制文件:
chmod +x /usr/local/bin/docker-compose
# 创建软链
ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
# 验证是否安装成功
docker-compose --version

编写 docker-compose.yaml 文件

version: '1'
services: # 表示定义一些容器,下面每一个service就是docker中容器的名称
  python-app: # 容器名称
    build: . # 从当前目录的Dockerfile进行构建
    ports:
      - "5000:5000" # 端口的映射,和 -p 命令一样
    networks:
      - python-net # 使用这个网络

  redis: 
    image: "redis:alpine" # 从该镜像构建一个容器
    networks:
      - python-net

networks: # docker network create --name python-net
  python-net:
    driver: bridge # 创建一个python-net的网络,并指定为bridge类型的

使用 docker-compose.yaml 创建容器

# up表示启动  -d表示后台启动
# 如果有指定docker-compose.yaml文件,使用-f命令指定
docker-compose up -d

docker-compose文件详解

# service表示一个容器
# ports表示映射的端口号,相当于-p
# build表示要根据Dockerfile文件构建镜像
# networks表示创建网络,service下面指定networks参数表示使用该网络
# images表示指定从指定镜像创建service
# volumes表示指定数据卷,相当于-v v1:/var/lib/mysql
# enviornment表示参数,相当于-e

docker-compose常见操作

# 查看版本
docker-compose version
# 根据yml创建service
docker-compose up
# 指定yaml:docker-compose  up -f xxx.yaml
# 后台运行:docker-compose up
#查看启动成功的service
docker-compose ps
# 也可以使用docker ps
# 查看images
docker-compose images
#停止/启动service
docker-compose stop/start 
# 删除service[同时会删除掉network和volume]
docker-compose down
# 进入到某个service
docker-compose exec redis sh
十一、docker-swarm

docker-swarm是为了解决在多机部署容器

manager-node:2200

work01-node:2201

work02-node:2202

1.安装docker-swarm

进入manager

docker swarm init --advertise-addr=192.168.0.11

显示以下内容,复制圈住的内容

在其他两个worker节点执行该命令

docker swarm join --token SWMTKN-1-12nfretcz1e6jgguiifz5by9ntb2tuzdtjbc8znw9465n8nir6-93l1j9flq85rhxgvyf62ym0q7 192.168.0.11:2377

查看集群状态

docker node ls

可以看到manager-node节点的MANAGER STATUS为Leader

node类型的转换,可以将worker提升成manager,从而保证manager的高可用

# 提成节点为候选的
docker node promote worker01-node
docker node promote worker02-node

#降级可以用demote
docker node demote worker01-node
2.docker-swarm基本操作

创建一个service

docker service create --name tomcat01 tomcat

查看当前swarm的service

docker service ls

查看日志详情

docker service logs tomcat01

查看service的详情

docker service inspect tomcat01

查看容器运行在哪个节点上面

docker service ps tomcat01
# 输出以下内容,随机运行在某一个节点上面
ID             NAME         IMAGE           NODE            DESIRED STATE   CURRENT STATE         ERROR     PORTS
pawlnlhurroa   tomcat01.1   tomcat:latest   worker01-node   Running         Running 6 hours ago 

水平扩容service

docker service scale tomcat01=3
# 查看列表
docker service ls
# 查看详情
docker service ps my-tomcat
# 输出一下内容
ID             NAME         IMAGE           NODE            DESIRED STATE   CURRENT STATE              ERROR     PORTS
pawlnlhurroa   tomcat01.1   tomcat:latest   worker01-node   Running         Running 7 hours ago                  
xg6yne73yug2   tomcat01.2   tomcat:latest   manager-node    Running         Running 12 minutes ago               
xig0y6lgaoiy   tomcat01.3   tomcat:latest   worker02-node   Running         Preparing 12 minutes ago  

此时到worker01-node上:docker ps,可以发现container的name和service名称不一样

docker ps
# 显示一下内容
CONTAINER ID   IMAGE           COMMAND             CREATED       STATUS       PORTS      NAMES
f8fa8f859a1f   tomcat:latest   "catalina.sh run"   7 hours ago   Up 7 hours   8080/tcp   tomcat01.1.pawlnlhurroa78izqtc21zyjm

如果某个node上的my-tomcat挂掉了,这时候会自动扩展

# [worker01-node]
docker rm -f containerid

# [manager-node]
docker service ls
docker service ps my-tomcat

删除service

docker service rm my-tomcat
3.Swarm中部署一个个人博客

(1)创建一个overlay网络,用于docker swarm中多机通信

# manager节点执行
docker network create -d overlay my-overlay-net

# 此时worker node查看不到
docker network ls

(2)创建mysql的service

# manager节点创建service
docker service create --name mysql --mount type=volume,source=v1,destination=/var/lib/mysql --env MYSQL_ROOT_PASSWORD=examplepass --env MYSQL_DATABASE=db_wordpress --network my-overlay-net mysql:5.6

#查看service
docker service ls
docker service ps mysql

(3)创建wordpress的service

# 创建service  [注意之所以下面可以通过mysql名字访问,也是因为有DNS解析]
docker service create --name wordpress --env WORDPRESS_DB_USER=root --env WORDPRESS_DB_PASSWORD=examplepass --env WORDPRESS_DB_HOST=mysql:3306 --env WORDPRESS_DB_NAME=db_wordpress -p 8080:80 --network my-overlay-net wordpress

# 查看service
docker service ls
docker service ps mysql
	
# 此时mysql和wordpress的service运行在哪个node上,这时候就能看到my-overlay-net的网络

(4)测试

win浏览器访问ip[manager/worker01/worker02]:8080都能访问成功

(5)查看my-overlay-net

docker network inspect my-overlay-net

(6)为什么没有用etcd?docker swarm中有自己的分布式存储机制

4. Routing Mesh (1) Ingress
docker service create --name tomcat  -p 8080:8080 --network my-overlay-net tomcat

记得使用一个自定义的overlay类型的网络

--network my-overlay-net

查看service情况

docker service ls
docker service ps tomcat

访问3台机器的ip:8080测试,发现都能够访问到tomcat的欢迎页

(2) Internal

之前在实战wordpress+mysql的时候,发现wordpress中可以直接通过mysql名称访问

这样可以说明两点,第一是其中一定有dns解析,第二是两个service的ip是能够ping通的

再创建一个service,也同样使用上述tomcat的overlay网络,然后来实验

docker service create --name whoami -p 8000:8000 --network my-overlay-net -d  jwilder/whoami

查看whoami的情况

docker service ps whoami

在各自容器中互相ping一下彼此,也就是容器间的通信

#tomcat容器中ping whoami
docker exec -it 9d7d4c2b1b80 ping whoami
64 bytes from bogon (10.0.0.8): icmp_seq=1 ttl=64 time=0.050 ms
64 bytes from bogon (10.0.0.8): icmp_seq=2 ttl=64 time=0.080 ms


#whoami容器中ping tomcat
docker exec -it 5c4fe39e7f60 ping tomcat
64 bytes from bogon (10.0.0.18): icmp_seq=1 ttl=64 time=0.050 ms
64 bytes from bogon (10.0.0.18): icmp_seq=2 ttl=64 time=0.080 ms

将whoami进行扩容

docker service scale whoami=3
docker service ps whoami     #manager,worker01,worker02

此时再ping whoami service,并且访问whoami服务

#ping
docker exec -it 9d7d4c2b1b80 ping whoami
64 bytes from bogon (10.0.0.8): icmp_seq=1 ttl=64 time=0.055 ms
64 bytes from bogon (10.0.0.8): icmp_seq=2 ttl=64 time=0.084 ms

#访问
docker exec -it 9d7d4c2b1b80 curl whoami:8000  [多访问几次]
I'm 09f4158c81ae
I'm aebc574dc990
I'm 7755bc7da921

whoami服务对其他服务暴露的ip是不变的,但是通过whoami名称访问8000端口,确实访问到的是不同的service。

也就是说whoami service对其他服务提供了一个统一的VIP入口,别的服务访问时会做负载均衡。

(3) Stack

docker stack deploy:https://docs.docker.com/engine/reference/commandline/stack_deploy/

compose-file:https://docs.docker.com/compose/compose-file/

docker swarm中的Stack,我们直接通过前面的wordpress+mysql案例看看怎么使用咯。

新建service.yml文件

version: '3'

services:

  wordpress:
    image: wordpress
    ports:
      - 8080:80
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: exampleuser
      WORDPRESS_DB_PASSWORD: examplepass
      WORDPRESS_DB_NAME: exampledb
    networks:
      - ol-net
    volumes:
      - wordpress:/var/www/html
    deploy:
      mode: replicated
      replicas: 3
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
      update_config:
        parallelism: 1
        delay: 10s

  db:
    image: mysql:5.7
    environment:
      MYSQL_DATABASE: exampledb
      MYSQL_USER: exampleuser
      MYSQL_PASSWORD: examplepass
      MYSQL_RANDOM_ROOT_PASSWORD: '1'
    volumes:
      - db:/var/lib/mysql
    networks:
      - ol-net
    deploy:
      mode: global
      placement:
        constraints:
          - node.role == manager

volumes:
  wordpress:
  db:

networks:
  ol-net:
    driver: overlay

根据service.yml创建service

docker stack deploy -c service.yml my-service

常见操作

# 查看stack具体信息
docker stack ls
NAME                SERVICES            ORCHESTRATOR
my-service          2                   Swarm
	
#查看具体的service
docker stack services my-service
	
ID                  NAME                   MODE                REPLICAS            IMAGE               PORTS
icraimlesu61        my-service_db          global              1/1                 mysql:5.7           
iud2g140za5c        my-service_wordpress   replicated          3/3                 wordpress:latest    *:8080->80/tcp

# 查看某个service
docker service inspect my-service-db
	
"Endpoint": {
            "Spec": {
                "Mode": "vip"
            },
            "VirtualIPs": [
                {
                    "NetworkID": "kz1reu3yxxpwp1lvnrraw0uq6",
                    "Addr": "10.0.1.5/24"
                }
            ]
        }

(4)访问测试

win浏览器ip[manager,worker01,worker02]:8080

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/940268.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号