Docker进阶

26

Docker进阶

Dockerfile

参考资料地址:Dockerfile reference | Docker Docs
Dockerfile是用来构建镜像的文本文件,在没有Dockerfile文件以前,构建镜像需要通过不断commit容器来完成,有了Dockerfile后,我们只需要编写Dockerfile文件,然后运行构建命令就可以了。

支持的命令

下面将对Dockerfile文件中支持的命令进行说明。需要说明的是Dockerfile文件中的命令需要大写。

  • FROM:一般写在首行,用来指定基础镜像。如FROM ubuntu
  • ENV:添加环境变量,环境变量可以在一些命令(CMD、WORKDIR)中被使用,通过$env_key的形式。如ENV JAVA_HOME /usr/local/java
  • WORKDIR:指定工作目录,对容器的操作都将基于该目录。如WORKDIR $basedir
  • RUN:指定在容器中运行的命令,构建镜像主要依赖该命令。如RUN apt install -y mysql-server
  • ADD:将宿主主机的文件夹或压缩包(tar)复制到容器中,如果是压缩包,将会自动进行解压。示例ADD test.txt /mydir/ADD <src> <des>
  • COPY:将宿主主机的文件夹或文件复制到容器中,该命令相对于ADD命令来说,不会进行解压操作。用法和ADD类似。
  • VOLUME:配置数据卷,对宿主主机目录和容器目录做映射。
  • EXPOSE:指定需要对外暴漏的端口,格式EXPOSE port。这个端口是指定容器去监听的,如果对容器和宿主主机端口做映射,需要通过-p参数来完成。
  • CMD:可以写多个CMD命令,但是只有最后一个生效,该命令是在我们docker run镜像后,容器启动后执行的第一条命令。同时需要注意的是,如果用户在docker run -d container_id的后面加了其他参数,那么会覆盖掉通过Dockerfile配置的最后一个CMD命令。示例CMD ./catalina.sh
  • ENTRYPOINT:优先级高于CMD命令,类似于CMD指令,但是ENTRYPOINT不会被docker run后面的命令覆盖,而且这些命令行参数会被当做参数送给ENTRYPOINT指令指定的程序。如果ENTRYPOINT后面紧跟着CMD命令,那么CMD的内容会被作为ENTRYPOINT中指定程序的参数。

案例

下面以hippo4j为例。
Dockerfile文件

# 基础镜像
FROM java8:1.0                    
ENV config_location /etc/hippo4j/application.properties                               
WORKDIR /usr/local/hippo4j/
COPY hippo4j-server.jar ./
VOLUME /etc/hippo4j/
EXPOSE 6691
CMD java -jar ./hippo4j-server.jar --spring.config.location=$config_location

构建命令

# 进入Dockerfile所在目录
cd hippo4j
# 别忘了最后面的.,表示构建工作目录
docker build -t hippo4j:1.0 .

Dockerfile实际上提供了一种链式创建容器的方式,通过编写一个Dockerfile文件,然后执行docker build -t image_name:version .命令来构建镜像。

Docker的网络模式

Docker支持四种网络模式,准确来说是三种,下面将一一说明。

网络模式说明
bridge桥接模式,默认网络模式为bridge。该模式下,容器会使用docker模拟的网卡
host主机模式,该模式下,容器和宿主机共用同一张网卡
none该模式会禁用网络功能,仅有本地回环网络可用
container与某个容器共用网络配置。但是如果主容器被停止,那么网络将不可用

桥接模式

Docker服务默认会创建一个docker0网桥(其上有一个docker0内部接口),该桥接网络的名称为docker0,它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到了同一个物理网络。Docker默认指定了docker0接口的IP地址和子网掩码,让主机和容器之间可以通过网桥相互通信。
桥接模式下,容器使用docker模拟的网卡,容器使用桥接网卡和宿主机之间进行通信,宿主机和容器之间的网络并不直接相连。
Docker Network Bridge示意图.png
如上图所示,网桥docker0提供veth接口,容器通过自己的网卡接口eth0和网桥相连。
指定网络模式为桥接模式的启动参数示例如下:

docker run -d --network bridge ubuntu

主机模式

主机模式下,容器和主机共享IP和端口。
指定网络模式为主机模式的启动参数示例如下:

docker run -d --network host ubuntu

容器模式

容器模式下,要启动的容器使用另一个容器的网络配置。需要注意的是如果主容器停止运行,那么使用该主机网络的容器的网络将不可用。
指定网络模式为主机模式的启动参数示例如下:

docker run -d --network container:container_name ubuntu

常用命令

命令描述
docker network ls列出docker目前所有的网络
docker network create -d bridge test创建网络,test为网络命令,可以通过-d指定网络模式
docker network inspect network_name查看网络详细配置
docker network rm network_name删除网络

自定义网络

对于运行在同一个鲸鱼背上的容器来说,每一次运行,如果使用的是默认的桥接网络,那么每次都会分配不同的IP,服务之间想要互相通信,只能通过IP,非常麻烦。我们可以通过自定义网络来解决这个问题。自定义网络达到的效果是可以直接用服务名来代替IP进行通信。使用自定义网络的步骤如下。

  1. 通过命令创建自定义网络
  2. 在启动容器时,通过--network参数设置网络为该自定义网络并通过--name设置服务名
  3. 在容器内,可以直接通过服务名进行通信

Docker-Compose

Docker Compose解决了容器与容器之间如何管理编排(比如依赖关系)的问题。可以用一个配置文件(docker-compose.yml)定义一个多容器的应用,然后使用一条指令安装这个应用的所有依赖,完成构建。一般来说,运维干着方面多一些。
官方文档地址:Compose file | Docker Docs
docker-compose是Docker官方提供的小工具,需要先进行安装。
使用Docker Compose可以干什么?

  • 通过docker-compsoe.yml文件定义一批服务,并通过命令快速启动
  • 支持定义容器启动顺序
  • 所有通过docker run命令配置的参数,docker-compose都可以配置
  • 一份配置,随处运行。避免每次启动容器都需要使用docker run命令

常用配置项

配置项配置路径说明
versionroot配置版本号,现阶段配"3"即可
servicesroot配置服务列表
networksroot配置网络,如果不存在,会进行创建
imageservices.service_name配置服务使用的镜像
container_nameservices.service_name配置容器名称,与--name参数作用相同
restartservices.service_name配置重启策略
depends_onservices.service_name配置当前服务依赖的其他服务,启动时,会先启动它们
networksservices.service_name配置当前服务使用的网络
volumesservices.service_name配置数据卷,与-v命令类似
portsservices.service_name配置端口映射
commandservices.service_name配置命令,不同镜像配置方式不同

常用命令

命令说明
docker-compose -h帮助
docker-compose up启动docker-compose服务
docker-compose up -d启动docker-compose服务并在后台运行
docker-compose down停止并删除容器,网络,卷,镜像
docker-compose exec yml服务id进入指定服务内部
docker-compose ps展示当前docker-compose编排过的所有容器
docker-compose top展示当前docker-compose编排过的容器进程
docker-compose logs yml服务id查看容器输出日志
docker-compose config -q检查配置,输出发现的问题
docker-compose restart重启服务
docker-compose start启动服务
docker-compose stop停止服务

案例

以Halo的配置为例。

# docker-compose配置文件版本
version: "3"
# 配置服务列表,子项为每个服务
services:
  halo:
    image: halohub/halo:2.11
    container_name: halo
    restart: on-failure:3
    depends_on:
      halodb:
        condition: service_healthy
    networks:
      halo_network:
    volumes:
      - ./halo2:/root/.halo2
    ports:
      - "8090:8090"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8090/actuator/health/readiness"]
      interval: 30s
      timeout: 5s
      retries: 5
      start_period: 30s
    command:
      - --spring.r2dbc.url=r2dbc:pool:mysql://halodb:3306/halo
      - --spring.r2dbc.username=root
      # MySQL 的密码,请保证与下方 MYSQL_ROOT_PASSWORD 的变量值一致。
      - --spring.r2dbc.password=o#DwN&JSa56
      - --spring.sql.init.platform=mysql
      # 外部访问地址,请根据实际需要修改
      - --halo.external-url=http://localhost:8090/

  halodb:
    image: mysql:8.1.0
    container_name: halodb
    restart: on-failure:3
    networks:
      halo_network:
    command: 
		# 支持的命令参数可以查看DockerHub上的官方说明
      - --default-authentication-plugin=caching_sha2_password
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_general_ci
      - --explicit_defaults_for_timestamp=true
    volumes:
      - ./mysql:/var/lib/mysql
      - ./mysqlBackup:/data/mysqlBackup
    ports:
      - "3306:3306"
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "--silent"]
      interval: 3s
      retries: 5
      start_period: 30s
    environment:
	  # 支持的env参数可以查看DockerHub上的官方说明
      # 请修改此密码,并对应修改上方 Halo 服务的 SPRING_R2DBC_PASSWORD 变量值
      - MYSQL_ROOT_PASSWORD=o#DwN&JSa56
      - MYSQL_DATABASE=halo
# 配置网络
networks:
  halo_network:

容器监控、统计

Portainer——轻量级

官方文档地址:Install Portainer CE with Docker on Linux - Portainer Documentation

CIG——中量级

CAdvisor:数据收集、聚合、分析等
InfluxDB:时序数据库,用来存放CAdvisor收集到的监控数据
Grafana:图形化界面展示,它是一个通用的数据展示工具,可以配置多种数据源
可以使用Docker-Compose进行安装

K8s——重量级