0
点赞
收藏
分享

微信扫一扫

Docker与微服务实战(进阶)

南陵王梁枫 2022-04-07 阅读 166

Docker与微服务实战(进阶)

八、DockerFile

8.1 是什么?

Dockerfile是用来构建Docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本

官网

8.2 DockerFile构建过程解析

构建三步骤

  1. 编写Dockerfile文件
  2. docker build命令构建镜像
  3. docker run依镜像运行容器实例

8.2.1 Dockerfile内容基础知识

1:每条保留字指令都必须为大写字母且后面要跟随至少一个参数

2:指令按照从上到下,顺序执行

3:#表示注释

4:每条指令都会创建一个新的镜像层并对镜像进行提交

8.2.2 Docker执行Dockerfile的大致流程

  1. docker从基础镜像运行一个容器
  2. 执行一条指令并对容器做出修改
  3. 执行类似docker commit的操作提交一个新的镜像层
  4. docker基于刚提交的镜像运行一个新容器
  5. 执行dockerfile中的下一条指令直到所有指令都执行完毕

8.2.3 小总结

从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段,

  • Dockerfile是软件的原材料
  • Docker镜像是软件的交付品
  • Docker容器则可以认为是软件镜像的运行态,也即依照镜像运行的容器实例
    Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。

image-20220405103302981

1 Dockerfile,需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;

2 Docker镜像,在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行 Docker镜像时会真正开始提供服务;

3 Docker容器,容器是直接提供服务的。

8.3 Dockerfile常用保留字指令

  • FROM 基础镜像,当前新镜像是基于哪个镜像的,指定一个已经存在的镜像作为模板,第一条必须是from

  • **MAINTAINER ** 这条命令主要是指定维护者信息,方便他人寻找作者 指令后面的内容其实没有规定写什么, 只要可以联系上作者即可,一般使用邮箱地址 格式为 MAINTAINER Name 。注意:这个标签已经弃用,但现在还有很多 Dockerfi 使用这个标签,所以短时间内不会删除 现在推荐使用更灵活的 LABEL 命令,详见 面的讲解。

  • EXPOSE 当前容器对外暴露出的端口

  • WORKDIR 指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点

  • USER 指定该镜像以什么样的用户去执行,如果都不指定,默认是root

  • ENV 用来在构建镜像过程中设置环境变量

  • ENV MY_PATH /usr/mytest
    这个环境变量可以在后续的任何RUN指令中使用,这就如同在命令前面指定了环境变量前缀一样;
    也可以在其它指令中直接使用这些环境变量,

    比如:WORKDIR $MY_PATH

  • ADD 将宿主机目录下的文件拷贝进镜像且会自动处理URL和解压tar压缩包

  • VOLUME 容器数据卷,用于数据保存和持久化工作

8.3.1 RUN

image-20220405104013642

shell格式: RUN yum -y install vim

到 shell 格式中,可以使用反斜杠将单个 RUN 命令跨到下一行

RUN echo ” Hello ”&& \

​ echo "World”\

&& echo ” Docker”

exec格式:RUN [“可执行文件”,“参数1”,“参数2”]

例:RUN [“./test.php”,“dev”,“offline”] 等价于 ./test.php dev offline

以这种格式运行程序,可以免除运行 n/sh 的消耗 这种格式是用 Ison 格式将程序名 与所需参 数组成一个字符串数组,所以如果参数中有引号等特殊字符,贝lj 需要进行转义

RUN是在 docker build时运行

  • COPY 类似ADD,拷贝文件和目录到镜像中。将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置

image-20220405104400946

8.3.2 CMD

image-20220405104724204

CMD是在docker run时运行

CMD指令可以有多条,但只有最后一个生效,CMD会被docker run后面的参数替换

image-20220405105228712

上面这个实例什么意思呢,官网编写的关于tomcat的Dockerfile文件的最后一行是运行catalina.sh脚本

image-20220405105643278

能访问tomcat

加上/bin/bash

则不能访问tomcat

FROM ubuntu  

CMD [echo ” , ” Hello Ubuntu” ] 

docker build -t user/test .

image-20220405113325401

docker run -it imageId echo "Hello Docker"这个方式启动容器时,echo "HelloDocker”命令会覆盖原有的CMD命令。也就是说,CMD 命令可以通过docker run命令覆盖,这一点也是CMD和ENTRYPOINT指令的最大区别。

image-20220405105139911

8.3.3 ENTRYPOINT

也是用来指定一个容器启动时要运行的命令

类似于 CMD 指令,但是ENTRYPOINT不会被docker run后面的命令覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序

FROM ubuntu

ENTRYPOINT [ ” echo” ]

image-20220405121627847

8.3.4 小总结

image-20220405121706206

8.4 Dockerfile实战

Redis容器化

(1)基础镜像:centos:centos7.5.1804;

(2)作者:Chinaskill;

(3)修改配置文件中的bind 127.0.0.1为bind 0.0.0.0;

(4)设置Redis免密,并关闭保护模式;

(5)开放端口:6379;

(6)设置服务开机自启。

[root@master redis]# cat Dockerfile 
FROM centos:centos7.5.1804
MAINTAINER Chinaskill
RUN rm -rf /etc/yum.repos.d/*
ADD ftp.repo /etc/yum.repos.d/ftp.repo
RUN yum clean all
RUN yum list
RUN yum install -y redis
RUN sed -i 's/bind 127.0.0.1/bind 0.0.0.0/g' /etc/redis.conf
RUN sed -i 's/protected-mode yes/protected-mode no/g' /etc/redis.conf
RUN sed -i 's/daemonize no/daemonize yes/g' /etc/redis.conf
EXPOSE 6379
ENTRYPOINT ["/usr/bin/redis-server","/etc/redis.conf"]

容器化MariaDB

(1)基础镜像:centos:centos7.5.1804;

(2)作者:Chinaskill;

(3)设置数据库密码:123456;

(4)创建数据库gpmall并导入数据库文件gpmall.sql;

(5)设置字符编码:UTF-8;

(6)开放端口:3306;

(7)设置服务开机自启。

[root@master redis]# cd /root/mariadb/
[root@master mariadb]# ls
Dockerfile ftp.repo gpmall.sql init.sh
[root@master mariadb]# cat Dockerfile 
FROM centos:centos7.5.1804
MAINTAINER Chinaskill
RUN rm -rf /etc/yum.repos.d/*
ADD ftp.repo /etc/yum.repos.d/
RUN yum install -y mariadb-server
ADD init.sh /root/init.sh
RUN chmod +x /root/init.sh
ADD gpmall.sql /root/gpmall.sql
RUN /root/init.sh
ENV C.LANG UTF-8
EXPOSE 3306
CMD ["mysqld_safe"]

容器化Zookeeper

(1)基础镜像:centos:centos7.5.1804;

(2)作者:Chinaskill;

(3)开放端口:2181;

(4)设置服务开机自启。

[root@master zookeeper]# ls

Dockerfile ftp.repo zookeeper-3.4.14.tar.gz

[root@master zookeeper]# cat Dockerfile 
FROM centos:centos7.5.1804
MAINTAINER Chinaskill
RUN rm -rvf /etc/yum.repos.d/*
COPY ftp.repo /etc/yum.repos.d/local.repo
RUN yum -y install java-1.8.0
ADD zookeeper-3.4.14.tar.gz /usr/local
ENV ZOOKEEPER_HOME /usr/local/zookeeper-3.4.14
ENV PATH $PATH:$JAVA_HOME/bin:$JRE_HOME/bin:$ZOOKEEPER_HOME/bin
RUN cp $ZOOKEEPER_HOME/conf/zoo_sample.cfg $ZOOKEEPER_HOME/conf/zoo.cfg
EXPOSE 2181
CMD $ZOOKEEPER_HOME/bin/zkServer.sh start-foreground

虚悬镜像

仓库名、标签都是的镜像,俗称dangling image

虚悬镜像的由来

通常出现这种情况,是因为构建了一个新镜像,然后为该镜像打了一个已经存在的标签。接着Docker会移除旧镜像上面的标签,将该标签标在新的镜像之上。例如,首先基于alpine:3.4构建一个新的镜像,并打上dodge:challenger标签。然后更新Dockerfile,将alpine:3.4替换为alpine:3.5,并且再次执行docker image build命令。该命令会构建一个新的镜像,并且标签为dodge:challenger,同时移除了旧镜像上面对应的标签,旧镜像就变成了悬虚镜像

查询显示虚悬镜像
docker images -f dangling=true
删除虚悬镜像
docker rmi $(docker images -q -f dangling=true)

九、微服务实战

1.修改之前的SpringBoot项目yml中数据库配置,改为容器化的mysql地址

image-20220406083234936

2.根据实体类新建数据库

DROP TABLE IF EXISTS user;

CREATE TABLE user
(
    id int(20) NOT NULL COMMENT '主键ID' auto_increment,
    name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
    age INT(11) NULL DEFAULT NULL COMMENT '年龄',
    email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
    PRIMARY KEY (id)
);

DELETE FROM user;
INSERT INTO user (id, name, age, email) VALUES
(1, 'Banana', 18, 'test1@pyy.com'),
(2, 'Jack', 20, 'test2@pyy.com'),
(3, 'Tom', 28, 'test3@pyy.com'),
(4, 'Milk', 21, 'test4@pyy.com'),
(6,'zs@qq',10,'asd'),
(5, 'Apple', 24, 'test5@pyy.com');

3.项目打包

image-20220405123335304

4. 容器化myqsl

docker run -d -p 3306:3306 --privileged=true -v /pyy/mysql/log:/var/log/mysql -v /pyy/mysql/data:/var/lib/mysql -v /pyy/mysql/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=a --name mysql mysql:5.7

image-20220406083505545

5. 构建镜像

[root@VM-16-8-centos springboot_test]# cat Dockerfile
FROM java:8
MAINTAINER pyy
VOLUME /tmp
ADD sys-admin-0.0.1-SNAPSHOT.jar pyy_docker.jar
RUN bash -c ‘touch /pyy_docker.jar’
ENTRYPOINT [“java”,“-jar”,“/pyy_docker.jar”]
EXPOSE 8080

docker build -t pyy_docker:1.0 .

6.运行容器

docker run -d -p 8080:8080 pyy_docker:1.6

image-20220406084507695

7.测试

image-20220406084548796

十、网络模式

10.1 简介

docker不启动,默认网络情况

  • ens33
  • lo
  • virbr0

docker启动后,网络情况

[root@VM-16-8-centos springboot_test]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
2c74a4b5d76a   bridge    bridge    local
dd3008378058   host      host      local
9ebd6b25e4c3   none      null      local

常用命令

查看网络

docker network ls

查看网络源数据

docker network inspect XXX网络名字

删除网络

docker network rm XXX网络名字

案例

[root@VM-16-8-centos springboot_test]# docker network create test_docker_network
7a7c98e51c6effc0498579ec3cf9bfe6b0a9052ae8c3996781f61389b2529165
[root@VM-16-8-centos springboot_test]# docker network ls
NETWORK ID     NAME                  DRIVER    SCOPE
2c74a4b5d76a   bridge                bridge    local
dd3008378058   host                  host      local
9ebd6b25e4c3   none                  null      local
7a7c98e51c6e   test_docker_network   bridge    local
[root@VM-16-8-centos springboot_test]# docker network rm test_docker_network
test_docker_network
[root@VM-16-8-centos springboot_test]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
2c74a4b5d76a   bridge    bridge    local
dd3008378058   host      host      local
9ebd6b25e4c3   none      null      local

网络模式能干嘛

容器间的互联和通信以及端口映射

容器IP变动时候可以通过服务名直接网络通信而不受到影响

小总结

image-20220406090336141

  • bridge模式:使用–network bridge指定,默认使用docker0
  • host模式:使用–network host指定
  • none模式:使用–network none指定
  • container模式:使用–network container:NAME或者容器ID指定

容器实例内默认网络IP生产规则

运行centos1和centos2,查看它们的ip分别为172.16.0.2,172.16.0.3。那么当centos2挂掉的话,在新建容器centos3,那么它的ip就会变为172.16.0.3

10.2 bridge

Docker 服务默认会创建一个 docker0 网桥(其上有一个 docker0 内部接口),该桥接网络的名称为docker0,==它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。==Docker 默认指定了 docker0 接口 的 IP 地址和子网掩码,让主机和容器之间可以通过网桥相互通信。

1 Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。

2 docker run 的时候,没有指定network的话默认使用的网桥模式就是bridge=,使用的就是docker0。在宿主机ifconfig,就可以看到docker0和自己create的network(后面讲)eth0,eth1,eth2……代表网卡一,网卡二,网卡三……,lo代表127.0.0.1,即localhost,inet addr用来表示网卡的IP地址

3 网桥docker0创建一对对等虚拟设备接口一个叫veth,另一个叫eth0,成对匹配
3.1 整个宿主机的网桥模式都是docker0,类似一个交换机有一堆接口,每个接口叫veth,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫veth pair);
3.2 每个容器实例内部也有一块网卡,每个接口叫eth0;
3.3 docker0上面的每个veth匹配某个容器实例内部的eth0,两两配对,一一匹配。
通过上述,将宿主机上的所有容器都连接到这个内部网络上,两个容器在同一个网络下,会从这个网关下各自拿到分配的ip,此时两个容器的网络是互通的。

image-20220406091532965

image-20220406091916322

image-20220406092125307

10.3 host

直接使用宿主机的 IP 地址与外界进行通信,不再需要额外进行NAT 转换。

容器将不会获得一个独立的Network Namespace, 而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡而是使用宿主机的IP和端口。

错误的写法:

docker run -d -p 8083:8080 --network host --name tomcat83 pyy/tomcat8-jdk8

正确的写法

docker run -d --network host --name tomcat83 pyy/tomcat8-jdk8

image-20220406092343717

http://宿主机IP:8080/

在CentOS里面用默认的火狐浏览器访问容器内的tomcat83看到访问成功,因为此时容器的IP借用主机的,
所以容器共享宿主机网络IP,这样的好处是外部主机与容器可以直接通信。

10.4 none

在none模式下,并不为Docker容器进行任何网络配置。
也就是说,这个Docker容器没有网卡、IP、路由等信息,只有一个lo
需要我们自己为Docker容器添加网卡、配置IP等。

image-20220406092902863

10.5 container

新建的容器和已经存在的一个容器共享一个网络ip配置而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的.

image-20220406093118037

docker run -d -p 8086:8080 --network container:tomcat85 --name tomcat86 billygoo/tomcat8-jdk8

image-20220406093839711

关闭alpine1,在看alpine2image-20220406094014970

10.6 自定义网络

image-20220406094316737

十一、容器编排

11.1 简介

Compose 是 Docker 公司推出的一个工具软件,可以管理多个 Docker 容器组成一个应用。你需要定义一个 YAML 格式的配置文件docker-compose.yml,写好多个容器之间的调用关系。然后,只要一个命令,就能同时启动/关闭这些容器

能干嘛

docker建议我们每一个容器中只运行一个服务,因为docker容器本身占用资源极少,所以最好是将每个服务单独的分割开来但是这样我们又面临了一个问题?

如果我需要同时部署好多个服务,难道要每个服务单独写Dockerfile然后在构建镜像,构建容器,这样累都累死了,所以docker官方给我们提供了docker-compose多服务部署的工具

例如要实现一个Web微服务项目,除了Web服务容器本身,往往还需要再加上后端的数据库mysql服务容器,redis服务器,注册中心eureka,甚至还包括负载均衡容器等等。。。。。。

Compose允许用户通过一个单独的docker-compose.yml模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project)。

可以很容易地用一个配置文件定义一个多容器的应用,然后使用一条指令安装这个应用的所有依赖,完成构建。Docker-Compose 解决了容器与容器之间如何管理编排的问题。

安装

[root@VM-16-8-centos springboot_test]# curl -L "https://github.com/docker/compose/releases/download/1.29.2
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   664  100   664    0     0    982      0 --:--:-- --:--:-- --:--:--   982
100 12.1M  100 12.1M    0     0  29870      0  0:07:06  0:07:06 --:--:-- 64748
[root@VM-16-8-centos springboot_test]# chmod +x /usr/local/bin/docker-compose
[root@VM-16-8-centos springboot_test]# cd /usr/local/bin/
[root@VM-16-8-centos bin]# vim docker-compose 
[root@VM-16-8-centos bin]# ll
total 13420
-rwxr-xr-x 1 root root  1001112 Aug  5  2020 busybox-x86_64
-rwxr-xr-x 1 root root 12737304 Apr  6 10:17 docker-compose
[root@VM-16-8-centos bin]# docker-compose --version
docker-compose version 1.29.2, build 5becea4c

11.2 docker-compose核心

一文件

docker-compose.yml

两要素

服务(service)

一个个应用容器实例,比如订单微服务、库存微服务、mysql容器、nginx容器或者redis容器

工程(project)

由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义。

Compose使用的三个步骤

  1. 编写Dockerfile定义各个微服务应用并构建出对应的镜像文件
  2. 使用 docker-compose.yml 定义一个完整业务单元,安排好整体应用中的各个容器服务。
  3. 最后,执行docker-compose up命令 来启动并运行整个应用程序,完成一键部署上线

11.3 Compose常用命令

docker-compose -h # 查看帮助
docker-compose up # 启动所有docker-compose服务
docker-compose up -d # 启动所有docker-compose服务并后台运行
docker-compose down # 停止并删除容器、网络、卷、镜像。
docker-compose exec yml里面的服务id # 进入容器实例内部 docker-compose exec docker-compose.yml文件中写的服务id /bin/bash
docker-compose ps # 展示当前docker-compose编排过的运行的所有容器
docker-compose top # 展示当前docker-compose编排过的容器进程

docker-compose logs yml里面的服务id # 查看容器输出日志
docker-compose config # 检查配置
docker-compose config -q # 检查配置,有问题才有输出
docker-compose restart # 重启服务
docker-compose start # 启动服务
docker-compose stop # 停止服务

11.4 快速入门Compose

跟着官网写个wordpress来写个实例

创建目录my_wordpress

进入目录,创建docker-compose.yml文件

version: "3.9"
    
services:
  db:
    image: mysql:5.7
    volumes:
      - db_data:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: somewordpress
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress
    
  wordpress:
    depends_on:
      - db
    image: wordpress:latest
    volumes:
      - wordpress_data:/var/www/html
    ports:
      - "8000:80"
    restart: always
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress
      WORDPRESS_DB_NAME: wordpress
volumes:
  db_data: {}
  wordpress_data: {}

docker-compose up -d项目目录运行。

[root@VM-16-8-centos my_wordpress]# docker-compose up -d
Creating network "my_wordpress_default" with the default driver
Creating volume "my_wordpress_db_data" with default driver
Creating volume "my_wordpress_wordpress_data" with default driver
Pulling wordpress (wordpress:latest)...
latest: Pulling from library/wordpress
c229119241af: Already exists
47e86af584f1: Pull complete
e1bd55b3ae5f: Downloading [====>                                              ]  7.903MB/91.6MB
e1bd55b3ae5f: Pull complete
1f3a70af964a: Pull complete
0f5086159710: Pull complete
7d9c764dc190: Pull complete
ec2bb7a6eead: Pull complete
9d9132470f34: Pull complete
fb23ab197126: Pull complete
cbdd566be443: Pull complete
be224cc1ae0f: Pull complete
629912c3cae4: Pull complete
f1bae9b2bf5b: Pull complete
19542807523e: Pull complete
59191c568fb8: Pull complete
30be9b012597: Pull complete
bb41528d36dd: Pull complete
bfd3efbb7409: Pull complete
7f19a53dfc12: Pull complete
23dc552fade0: Pull complete
5133d8c158a7: Pull complete
Digest: sha256:c8d7b938e831b715cf16f22b678f9c7a0ffd5e5efa9b9b2d77f39bed5cf5b2fd
Status: Downloaded newer image for wordpress:latest
Creating my_wordpress_db_1 ... done
Creating my_wordpress_wordpress_1 ... done

测试

image-2022040713525984

十二、Portainer

12.1 是什么

Portainer 是一款轻量级的应用,它提供了图形化界面,用于方便地管理Docker环境,包括单机环境和集群环境。

12.2 安装

官网

image-20220407141316883

因为我docker环境部署在了云服务器上,所以直接选本地即可

image-20220407141559059

image-20220407141903885

image-20220407143128082

测试

image-20220407143207736

docker stats

image-20220407143611100

十三、CAdvisor+InfluxDB+Granfana

docker ps

docker stats

13.1 容器监控三剑客

CAdvisor监控收集+InfluxDB存储数据+Granfana展示图表

image-20220407191755111

下面我们用docker-compose一键部署三剑客

version: '3.1'
 
volumes:
  grafana_data: {}
 
services:
 influxdb:
  image: tutum/influxdb:0.9
  restart: always
  environment:
    - PRE_CREATE_DB=cadvisor
  ports:
    - "8083:8083"
    - "8086:8086"
  volumes:
    - ./data/influxdb:/data
 
 cadvisor:
  image: google/cadvisor
  links:
    - influxdb:influxsrv
  command: -storage_driver=influxdb -storage_driver_db=cadvisor -storage_driver_host=influxsrv:8086
  restart: always
  ports:
    - "8080:8080"
  volumes:
    - /:/rootfs:ro
    - /var/run:/var/run:rw
    - /sys:/sys:ro
    - /var/lib/docker/:/var/lib/docker:ro
 
 grafana:
  user: "104"
  image: grafana/grafana
  user: "104"
  restart: always
  links:
    - influxdb:influxsrv
  ports:
    - "3000:3000"
  volumes:
    - grafana_data:/var/lib/grafana
  environment:
    - HTTP_USER=admin
    - HTTP_PASS=admin
    - INFLUXDB_HOST=influxsrv
    - INFLUXDB_PORT=8086
    - INFLUXDB_NAME=cadvisor
    - INFLUXDB_USER=root
    - INFLUXDB_PASS=root

image-20220407165542929

举报

相关推荐

0 条评论