一.Docker 概念
- 什么是docker
- docker是开发,运行和部署应用程序的开发管理平台
- 开发人员能利用docker开发和运行应用程序
- 运维认为能利用docker部署和管理应用程序
- docker 结构概览图
- client — server ----registry
- 一个客户端可以连接多个客户端,就和mysql一样可以连接远程数据库
- docker底层使用技术
- 使用Go语言实现
- 使用linux内核特性实现功能
- 使用linux的命名空间:为docker容器提供系统层面的隔离
- 使用linux控制组:为docker容器提供硬件层面的隔离
- 使用linux联合文件系统:利用layzer来使容器,镜像分离
- docker版本
- docker-ce 和docker-ee
- 社区版
- 企业版
- stable(按季度) 和 edge(按月)发行版本
- docker加速器配置文件
- /etc/docker/daemon.json
- 必须为标准的json格式
- 错误提示:”systemctl status docker.service“ and “journalctl -xe” for details
Docker 镜像
- docker search [-f] name 搜寻某个镜像
- docker images 查看本地镜像
- docker pull centos:7 指定版本号下载
- 执行顺序:
- 首先去search 该名字该版本的 image id
- 比对本地镜像中有没有该image id 有的话就不去下载,没有去下载
- docker rmi [options] image [image] 删除某个镜像
- docker rmi name:版本/image id
- docker rmi -f name:版本/image id 强制删除就算已经运行成了容器
- docker save [name:版本/image id] > linux.tar 可以多个打包镜像
- -o linux.tar 两种格式
- save方法如果用Image id来打包将在加载的时候显示none
- docker load -i 文件名 读取文件
- docker tag 原镜像 镜像名:版本名
- 重命名镜像
- name和版本是none 的直接覆盖名字
- 不是none的新建一个引用
- docker image inspect 名 查看描述中的信息
- docker image inspect 名 | grep Data
- docker image inspect -f “{{json .xx.xxx}}” 名 能指定具体字段{ }的所有内容
- docker history 名 查看镜像的历史信息
Docker容器
- 概念:将镜像运行起来后的实例
- docker ps 查看正在运行的容器
- docker ps -a 查看创建了的容器
- 和虚拟机比较
- 相同点:
- 对物理硬件资源进行共享使用
- 生命周期相似(创建、运行、暂停、关闭)
- 可以安装各种应用,和在虚拟机中操作一样
- 存储在宿主机上,linux为于/var/lib/docker/container下
- 区别:
- 虚拟机需要运行完整的操作系统,容器直接运行在宿主机内核上,不需要完整的操作系统
- 容器是轻量的(类似进程),虚拟机是重量的(类似操作系统)
- 和虚拟机的生命周期比较
- 虚拟机的生命周期:
- 镜像、created 创建、running 运行、paused 暂停、exited 退出(强行关闭和关闭)、deleted
- 容器的生命周期:
- 和虚拟机一样,但是没有可视化界面、docker created、docker run、docker pause、docker stop/docker kill、docker rm -f
- create命令
- docker create centos (默认为 /bin/bash)
- docker create --name centos-test centos
- docker create -ti centos python (-t 分配一个终端,-i交互)
- rm命令
- start
- created 状态
- stop状态
- 参数 -a 会输出到当前终端
- 参数 -ti 提供一个交互终端
- run (根据一个镜像,创建并启动一个容器)
- docker run 前台模式 默认省略了-a
- docker run centos ls -a
- docker run -ti centos python
- docker run -d 后台模式
- –rm 关闭的时候自动删除
- stop/kill 关闭容器
- -t 2 等待两秒关闭
- kill 和 kIll -9
- terminate(告诉进程给点时间关闭) kill(直接关闭不给时间)
- pause 暂停
- restart 重启
- logs 查看commend输出结果
- 容器运行时操作
- docker attach
- 标准的输入输出绑定到主进程,退出终端的时候,容器也会停止
- docker exec 名 python/bash
容器与镜像的关系
- docker commit -m ‘xxx’ id name:版本 基于原来容器生成一个新镜像
- docker run -dit xxx bash
- docker export -o net-tools.tar id将一个容器变成打包文件
- docker import -m ‘xxx’ tar文件 名字:版本号 将容器tar文件还原成镜像
- commit 和 import 的区别
- commit 会保留历史信息
- import 会全新的
- docker 容器和镜像的工作原理
- layzers
- histroy命令
- 只有更改过文件(就算文件大小为0)的才会在layzer上显示
- 联合文件系统,就和CSS一样
- 联合文件系统:运行成容器之后,上面有一层可读可写的一层,然后commit成镜像read-layer=>read-write layzer
docker网络管理
- docker network ls 查看当前的网络
- bridge
- host
- null
- overlay
- mavlen
- null 和 host只能存在一个网络,overlay必须依赖swarm
- docker network create 创建一个网络
- -d 指定网络驱动
- 指定子网网络
- 执行容器的IP范围
- 网关
- docker network rm id 删除网络
- docker inspect 网络名 网络的详细信息
- docker run --network mybridge -dti centos bash 默认使用bridge
- host 和bridge默认有网
- docker network disconnect 网络名 id 让某容器的网络断开
- docker network connect 网络名 id 让某容器的网络连接
- bridge 网络模式
- 当创建bridge网络之后,会宿主机上出现一个网关
- 容器之间,容器与宿主机之间的网络通信,借助为每一个容器生成一对veth pair虚拟网络设备对,所以运行一个带bridge的容器会生成一个网卡
- docker0 --》虚拟设备对通信
- docker run -dti -P redis
- -P 暴露端口随机映射
- -p [HOST_IP]:[HOST_PORT]:CONTAINER_PORT 指定端口暴露
- 两个都不写默认随机映射
- host不写,默认局域网的ip都可以
- host 网络模式
- 容器的网络就是宿主机的网络
- 同一个网络,相同的端口只能用一次
- 性能是最好的,不需要前面的桥和虚拟设备对
- container 网络模式
- 特殊的网络模式
- 容器共享其他的网络
- docker run -dti --network container:id 名
- 端口不能一样
- none 网络模式
- overlay 覆盖网络
- vxlan隧道技术实现
- 实现跨主机容器之间的通信
- 管理成败上千个跨主机的容器集群
- 工作原理
- macvlan
- 网络隔离
- 内部维护一张Mac地址表
- 根据mac地址数据转发,比bridge根据ip快
- 相当于在外部看来是另一台主机
docker数据卷
- 特点
- 独立于容器,和容器的生命周期分离
- 可以是目录也可以是文件,实现数据共享
- 容器初始化时,如果容器使用的镜像包含了数据,这些数据会拷贝到数据卷中
- 容器对数据卷的修改是实时进行的
- 数据卷的变化不会影响镜像的更新,镜像于数据卷之间不会相互影响
- 挂载的三种方式 都是通过 docker run/create
- bind mounts 挂载到容器中,映射
- volumes 由docker封装映射
- tmpfs mounts 基于内存的临时文件系统
- bind mounts 方式挂载数据卷
- -v /root/volume_dir:/root/c_dir (宿主机的目录:容器中的目录)
- –mount type=bind,src=/root/mount_dir,dst=/root/c2-dir
- volumes方式挂载数据卷
- -v volume对象的名称:/路径
- 数据卷不存在会自动创建
- 可以不给数据卷对象名,会随机分配
- –mount type=volume,src=volume对象的名称,dst=/路径
- docker volume create 创建数据卷
- 目录默认在 /var/lib/docker
- tmpfs mount方式挂载数据卷
- –mount type=tmpfs,dst=path
- –volumns-from id 和已经挂载数据卷的容器共用数据卷
- 注意:
- 如果挂载一个空的数据卷,而目的是有数据的,则会复制到数据卷中
- 如果挂载一个非空的数据卷到容器中的一个目录中,那么容器中的目录会显示数据卷中的数据;如果原来容器中的目录中有数据,那么这些原始数据会被隐藏掉
私有仓库
- 无认证私有仓库
- 安装docker
- 在服务器上下载registry
- 启动仓库
- docker run -dti --restart always --name my-registry -p 7999:5000 -v /my-registry/registry:/var/lib/registry registry
- 本机使用curl 127.0.0.1:7999/v2/_catalog 查看是否启动
- 上传
- 先将本地镜像更名
- 推送到私有仓库
- 先将推送变为http协议默认为https协议的推送
- 在/etc/docker/daemon.json中添加”insecure-registries“:[“服务器IP:端口”]
- 不安全的仓库就会用http协议
- docker push 服务器IP:端口/centos
- 下载
- 带认证的私有仓库
- 删除先前无认证的仓库
- 创建一个存放认证用户名和密码的文件
- mkdir /my-registry/auth -p
- 创建密码验证文件,注意将username 和password替换为设置的用户名和密码
- docker run --entrypoint htpasswd registry -Bbn username password > /my-registry/auth/htpasswd
- 重新启动仓库镜像
- docker run -d -p 7999:5000 --restart=always --name docker-registry -v /my-registry/registry:/var/lib/registry -v /my-registry/auth:/auth -e “REGISTRY_AUTH=htpasswd” -e “REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm” -e “REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd” registry
- 上传下载
- 先登录服务器
- docker login -u username -p password ip:端口
- 后面和无登录一样
- docker logout IP:端口 退出登录
Dockerfile
- 构建命令
- 第一次构建都会执行
- 第二次构建
- 先检测有没有变化再看是否执行
- 看哪一步开始改变,没改变的不执行
- build 的每一步都将会提交一个commit
- 编写的命令
- FROM:指定基础镜像
- RUN:构建镜像过程需要执行的命令,可以多条,只运行一次
- run yum -y install net-tools 以shell方式执行,子进程运行,可以访问当前的环境变量
- run [“yum”,”-y“,“install”…] 以exec方式执行,当前进程来执行,会把当前终端结束掉,再执行exec,无法访问当前的环境变量
- CMD:添加启动容器时需要执行的命令,多条只有最后一条生效,可以在启动容器时被覆盖和修改
- cmd [“execution”,“param1”]
- ENTRYPOINT:同cmd,但不会覆盖,一定会执行
- LABEL:为镜像添加对应的数据
- MAINTAINER:表示镜像的作者
- EXPOSE:设置对外暴露的端口
- ENV:设置执行命令的环境变量,并在构建完成后,仍然生效
- ARG:设置只在构建过程中使用的环境变量,构建完成后,将消失
- 可以动态 --build -arg user=username
- ADD:将本地或目录拷贝到镜像的文件系统中,能解压特定格式文件,能将URL作为要拷贝的文件(有可能解压失败)
- COPY:将本地文件或目录拷贝到镜像的文件系统中
- VOLUME:添加数据卷
- USER:指定以哪个用户的名义执行RUN等命令
- WORKDIR:设置工作目录(类似CD)
- ONBUILD 如果制作的镜像被另一个Dockerfile使用,将在哪里执行
- 配置文件
FROM python:alpine3.6
COPY ./flask-web-code /code
WORKDIR /code
RUN pip3 install -r requirements.txt
CMD ["python3","app.py"]
Docker-compose
- docker cli
- 安装:
- curl -L https://github.com/docker/compose/releases/download/1.25.4/docker-compose-$(uname -s)-$(uname -m) -o /usr/bin/docker-compose
- chmod +x /usr/bin/docker-compose
- docker-compose file
- 顶级配置项
- version:指定Docker Compose File版本号
- services:定义对个服务并配置启动参数
- volumes:声明或创建在多个服务中共同使用的数据卷对象
- networks:定义在多个服务中共同使用的网络对象
- configs:声明将在本服务中药使用的一些配置文件
- secrets:声明将在本服务中药使用的一些秘钥、密码文件
- x-***:自定义配置项
- 每个符号后面需要有一个空格
- docker-compose config来检查配置文件是否有错误
- docker-compose up -d可后台启动
- 慎用docker-compose down 删除了网络和容器和数据卷
- 配置文件
version: "3.6"
services:
flask-web:
build: .
ports:
- "5000:5000"
container_name: flask-web
networks:
- web
redis:
image: redis
container_name: flask
networks:
- web
volumes:
- redis-data:/data
networks:
web:
driver: bridge
volumes:
redis-data:
driver: local
- Docker Compose 单机环境ELK系统搭建
version: '2.2'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:6.2.4
container_name: elasticsearch
environment:
- cluster.name=docker-cluster
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- esdata1:/usr/share/elasticsearch/data
ports:
- 9200:9200
networks:
- esnet
elasticsearch2:
image: docker.elastic.co/elasticsearch/elasticsearch:6.2.4
container_name: elasticsearch2
environment:
- cluster.name=docker-cluster
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- "discovery.zen.ping.unicast.hosts=elasticsearch"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- esdata2:/usr/share/elasticsearch/data
networks:
- esnet
logstash:
image: docker.elastic.co/logstash/logstash:6.2.4
environment:
- "LS_JAVA_OPTS=-Xms256m -Xmx256m"
container_name: logstash
networks:
- esnet
depends_on:
- elasticsearch
- elasticsearch2
logstash2:
image: docker.elastic.co/logstash/logstash:6.2.4
environment:
- "LS_JAVA_OPTS=-Xms256m -Xmx256m"
container_name: logstash2
networks:
- esnet
depends_on:
- elasticsearch
- elasticsearch2
kibana:
image: docker.elastic.co/kibana/kibana:6.2.4
container_name: kibana
ports:
- "5601:5601"
networks:
- esnet
depends_on:
- elasticsearch
- elasticsearch2
volumes:
esdata1:
driver: local
esdata2:
driver: local
networks:
esnet:
- Docker Compose 多主机ELK部署
- 主节点
- docker swarm init 开启swarm 服务
- 记住docker swarm join那句话
- 其他节点
- 打docker swarm那句话
- 会多出docker_wgbridge这个网络
- 和ingress这个网络通信
- 查看配置文件
docker stack deploy -c docker-compose.yaml elk
- docker service logs 服务名 -f 动态查看 用这个查看集群日志
version: '3.6'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:6.2.4
environment:
- cluster.name=docker-cluster
- bootstrap.memory_lock=false
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
volumes:
- esdata1:/usr/share/elasticsearch/data
ports:
- 9200:9200
networks:
- esnet
deploy:
placement:
constraints:
- node.role == manager
elasticsearch2:
image: docker.elastic.co/elasticsearch/elasticsearch:6.2.4
environment:
- cluster.name=docker-cluster
- bootstrap.memory_lock=false
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- "discovery.zen.ping.unicast.hosts=elasticsearch"
volumes:
- esdata2:/usr/share/elasticsearch/data
networks:
- esnet
deploy:
placement:
constraints:
- node.role == worker
logstash:
image: docker.elastic.co/logstash/logstash:6.2.4
environment:
- "LS_JAVA_OPTS=-Xms256m -Xmx256m"
networks:
- esnet
deploy:
replicas: 2
logstash2:
image: docker.elastic.co/logstash/logstash:6.2.4
environment:
- "LS_JAVA_OPTS=-Xms256m -Xmx256m"
networks:
- esnet
deploy:
replicas: 2
kibana:
image: docker.elastic.co/kibana/kibana:6.2.4
ports:
- "5601:5601"
networks:
- esnet
deploy:
placement:
constraints:
- node.role == manager
volumes:
esdata1:
driver: local
esdata2:
driver: local
networks:
esnet:
driver: "overlay"