docker基础学习笔记

docker

一、概念

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。—— 百度百科

之前一直有一个误区,老听人说 Docker 是一个容器,应用程序打包好镜像,然后在这个容器中运行,以此达到 “一次封装,处处运行”(Build,Ship and Run Any App,Anywhere)的目的。其实不然,Docker 只是一个应用程序引擎(引擎的基础是Linux自带的容器(Linux Containers,LXC)技术),然后每一个进程都是一个容器 —— 运行于 Docker引擎上的容器。

Docker 在运行时分为 Docker 引擎(也就是服务端守护进程)和客户端工具。Docker 的引擎提供了一组 REST API,被称为 Docker Remote API,而如 docker 命令这样的客户端工具,则是通过这组 API 与 Docker 引擎交互,从而完成各种功能。因此,虽然表面上我们好像是在本机执行各种 docker 功能,但实际上,一切都是使用的远程调用形式在服务端(Docker 引擎)完成。也因为这种 C/S 设计,让我们操作远程服务器的 Docker 引擎变得轻而易举。

Client 和 Server可以运行在同一台集群,也可以通过跨主机实现远程通信。

传统的虚拟机技术和容器技术的区别?

传统虚拟机技术是虚拟出一套硬件后(内存分一点,磁盘分一点),在宿主上运行一个完整操作系统,在该系统上再运行所需要的应用进程;而容器内没有自己的内核,而且也没有进行硬件虚拟,应用进程直接运行于宿主的内核,而且进程和进程之间是相隔离的,是一个操作系统级别的虚拟化技术。

虚拟化技术通过 Hypervisor 实现虚拟机与底层硬件的解耦,虚拟机实现依赖 Hypervisor 层,Hypervisor 是整个虚拟机的核心所在。Hypervisor 虚拟机可以模拟机器硬件资源,协调虚拟机对硬件资源的访问,同时在各个虚拟机之间进行隔离。

虚拟化技术为用户提供了一个完整的虚拟机,包括操作系统在内。虚拟化技术有更佳的隔离性和安全性,但是更新和升级困难。

容器化技术为应用程序提供了隔离的运行空间,容器之间共享同一个上层操作系统内核。容器化具有快速扩展、灵活性和易用性等优势,但其隔离性较差、安全性相对较低。

实际部署一般是把两种技术结合起来,比如一个虚拟机中运行多个容器,这样既保证了较好的强隔离性和安全性,也有了快速扩展、灵活性和易用性。

Docker 的优势:

1、更高效的利用系统资源(不需要进行硬件虚拟以及运行完整操作系统等额外开销,一个相同配置的主机,往往可以运行更多数量的应用。单机支持上千个容器)
2、更快速的启动时间
3、一致的运行环境
4、持续交付和部署
5、更轻松的迁移
6、更轻松的维护和扩展

Docker 包括三个基本概念:

**镜像:**是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等) 。镜像不包含任何动态数据,其内容在构建之后也不会被改变,任何用户程序都可以成为镜像的一部分。

​ 镜像=操作系统+软件运行环境+用户程序。

**容器:**镜像和容器的关系,就像是面向对象程序设计中类和实例的关系,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

​ 容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立命名空间。容器内的进程是运行在一个隔离的环境中,使用起来,就好像是在一个独立于宿主的系统下操作一样。

​ 每一个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层,容器存储层的的生命周期和容器一样,容器消亡时,容器存储层也随之消亡。按照 Docker 的最佳实践,容器不应该向存储层写入任何数据,容器存储层要保持无状态变化。所有的文件写入操作,都应该使用 数据卷(Volume) 、或者绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储) 发生读写,其性能和稳定性更高。

**Docker Register:**一个集中的存储、分发镜像的服务,一个Docker Register 中可以包含多个仓库(打包好的软件镜像);每个仓库可以包含多个标签(一个软件的多个版本镜像);

tips:官方的镜像库 https://hub.docker.com/

​ 国内阿里云的镜像库 https://cr.console.aliyun.com/

daoker的安装

道云网址:get.dolcloud.io

官网网址 :Docker Hub Container Image Library | App Containerization

有网的情况下执行

yum update                                             #升级
curl -sSL https://get.daocloud.io/docker | sh          #下载并安装

安装完成后 执行 启动并开机自启

systemctl start docker
systemctl enable docker

rpm包下载地址: https://download.docker.com/linux/centos/7/x86_64/stable/Packages/

加速配置

curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s https://docker.mirrors.ustc.edu.cn/

该脚本可以将 --registry-mirror 加入到你的 Docker 配置文件 /etc/docker/daemon.json 中。适用于 Ubuntu14.04、Debian、CentOS6 、CentOS7、Fedora、Arch Linux、openSUSE Leap 42.1,其他版本可能有细微不同。更多详情请访问文档。

加速网址可以在网上找到 有时候有的网址是不好使的

下载完成后重启docker

systemctl restart docker

如果报错 则根据报错信息进行处理

Warning: docker.service changed on disk. Run 'systemctl daemon-reload' to reload units.
Job for docker.service failed because start of the service was attempted too often. See "systemctl status docker.service" and "journalctl -xe" for details.

此条报错执行下方命令即可

systemctl daemon-reload

docker的命令

基本用法 docker +命令关键字(command)+参数

docker run --name MyWordPress --link db:mysql -p 8080:80 -d wordpress

docker run 启动容器 --name 容器名 --link 关联其他容器 -p 将物理机8080端口映射到容器内的80端口 -d 后台运行 wordpress 启动的镜像 如止果后面跟版本则会指定版本号 如果没有版本则为最新版本标签 (latesr)

docker info	     	守护进程的系统资源设置
docker search	 	Docker 仓库的查询
docker pull	         Docker 仓库的下载
docker push         上传镜像  
docker tag  原镜像名 新镜像名   给镜像改名
docker login         登录镜像仓库               认证信息保存在 家目录/.docker/config.json
docker logout        登出镜像仓库               
docker save -o xx.tar镜像名 导出镜像为压缩文件
docker load -i xx.tar       从压缩文件导入镜像
docker build -t 账户名/镜像名:版本 .   封装镜像
  (--no-cache 不使用缓存   卸载最后)
history              镜像层级的描述
docker images		Docker 本地仓库镜像的查询
docker rmi -f	  	Docker	镜像的删除
docker ps	       	容器的查询
docker ps -a        查看退出容器
docker ps -q        简要化输出
docker run		    容器的创建启动
   (--name 容器名 )
   (--env INDEX_DATA=123 注入变量  卸载--name之后)
docker start/stop	容器启动停止
docker rm -f $( docker ps -a -q) 删除所有正在运行的容器    
将删除命令封装 
vim /usr/local/bin/cc   写入以下命令
#/bin/bash
docker rm -f $( docker ps -a -q)    保存退出
chmod +x /usr/local/bin/cc

每个容器被创建后,都会分配一个 CONTAINER ID 作为容器的唯一标示,后续对容器的启动、停止、修改、删除等所有操作,都是通过 CONTAINER ID 来完成,偏向于数据库概念中的主键

	docker ps --no-trunc			        查看完整版本
	docker stop/start CONTAINERID 	         停止
	docker start/stop MywordPress 	         通过容器别名启动/停止
	docker inspect MywordPress   	         查看容器所有基本信息
	docker image inspect                     查看当前镜像的元数据信息
	docker image inspect wangyanglinux:0.0.1 --format "{{json .ContainerConfig.Labels}}"
	      命令               镜像名             子选项     文件名   标签           子标签
	docker logs MywordPress  			    查看容器日志  并非真的查看日志查看的是前台程序输出的信息
	docker stats MywordPress  			    查看容器所占用的系统资源
	docker exec 容器名 容器内执行的命令  	    容器执行命令
	docker exec -it 容器名 /bin/bash  	       登入容器的bash
	docker cp 文件名 镜像名:目录               将文件名拷贝到容器中
    --restart=always   		     容器的自动启动
	-h x.xx.xx	 		        设置容器主机名
	--dns xx.xx.xx.xx	 		设置容器使用的 DNS 服务器
	--dns-search		         DNS 搜索设置
	--add-host hostname:IP		注入 hostname <> IP 解析
	--rm				       服务停止时自动删除    

docker-compose

docker三剑客

docker-compose 将一台机器上的多个项目进行统一化管理

docker-machine 将容器模拟为虚拟机

docker-swarm 容器的集群化设定

多容器管理

Docker 提倡理念是 “一个容器一个进程”,假设一个服务需要由多个进程组成,就需要多个容器组成一个系统,相互分工和配合对外提供完整服务
比如:博客系统
组件1:mariadb
组件2:WordPress 的 apache web

在启动容器是,同一台主机下如果两个容器之间需要由数据交流,使用 --link 选项建立两个容器之间的互联,前提是建立是 mariadb 已经开启
docker start db
docker start MywordPress
停止:
docker stop db MywordPress 或 docker stop MywordPress 在 docker stop db (注意关闭顺序)

docker-compose的安装

容器编排工具,允许用户在一个模板( YAML 格式 )中定义一组相关联的容器,会根据 --link 等参数,对启动的优先级进行排序

YAML语法

YAML 语言的设计目标,就是方便人类读写。它实质上是一种通用的数据串行化格式

基本语法规则
  • 大小写敏感
  • 使用缩进表示层级关系
  • 缩进是不使用 tab 键,只允许使用空格
  • 缩进的空格数目不重要,只要相同层级左侧的元素对其即可
  • " # " 表示注释,从这个字符一直到行尾都会被解释器忽略
数据类型
对象类型:对象是一组键值对,使用冒号结构表示
name: zhangsan

hash: {name: zhangsan, age: 18}
数组类型:一组连词线开头的行,构成一个数组
- 
  - zhangsan
  - lisi
  - wangwu
  
{name: ['zhangsan', 'lisi', 'wangwu']}
复合结构:对象和数组可以结合使用,形成复合结构
languages:
 - Ruby
 - Perl
 - Python 
websites:
 YAML: yaml.org 
 Ruby: ruby-lang.org 
 Python: python.org 
 Perl: use.perl.org 
纯量:纯量是最基本的、不可再分的值
  • 字符串
  • 布尔值
  • 整数
  • 浮点数
  • Null
  • 时间
  • 日期
# 数值直接以字面量的形式表示
number: 12.30

# 布尔值用 true 和 false 表示
isSet: true

# null 用 ~ 表示
parent: ~ 

# 时间采用 ISO8601 格式
iso8601: 2001-12-14t21:59:43.10-05:00

# 日期采用复合 iso8601 格式的年、月、日表示
date: 1976-07-31

# YAML 允许使用两个感叹号,强制转换数据类型
e: !!str 123
f: !!str true

# 字符串默认不使用引号表示
str: 这是一行字符串

# 如果字符串之中包含空格或特殊字符,需要放在引号之中
str: '内容: 字符串'

# 单引号和双引号都可以使用,双引号不会对特殊字符转义
s1: '内容\n字符串'
s2: "内容\n字符串"

# 单引号之中如果还有单引号,必须连续使用两个单引号转义
str: 'labor''s day' 

# 字符串可以写成多行,从第二行开始,必须有一个单空格缩进。换行符会被转为空格
str: 这是一段
  多行
  字符串
## { str: '这是一段 多行 字符串' }

# 多行字符串可以使用|保留换行符,也可以使用>折叠换行
this: |
  Foo
  Bar
that: >
  Foo
  Bar
## { this: 'Foo\nBar\n', that: 'Foo Bar\n' }

# +表示保留文字块末尾的换行,-表示删除字符串末尾的换行
s1: |
  Foo
 
s2: |+
  Foo
 
 
s3: |-
  Foo
  
## { s1: 'Foo\n', s2: 'Foo\n\n\n', s3: 'Foo' }

# 锚点&和别名*,可以用来引用
defaults: &defaults
  adapter:  postgres
  host:     localhost
 
development:
  database: myapp_development
  <<: *defaults
 
test:
  database: myapp_test
  <<: *defaults


docker-compose安装
curl -L https://github.com/docker/compose/releases/download/1.14.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose  

添加可执行权限

chmod a+x /usr/local/bin/docker-compose

查看是否可用

docker-compose version

yaml文件的创建和使用

mkdir /usr/local/wordpress      创建存放yaml文件的目录
vim docker-compose.yaml         创建yaml文件 文件后缀可以是yml 
写入文件内容
version: '2'

services:
   db:
     image: mysql:5.7
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: somewordpress
       MYSQL_DATABASE: wordpress
       MYSQL_USER: wordpress
       MYSQL_PASSWORD: wordpress

   wordpress:
     depends_on:
       - db
     image: wordpress:latest
     restart: always
     ports:
       - "8000:80"
     environment:
       WORDPRESS_DB_HOST: db:3306
       WORDPRESS_DB_USER: wordpress
       WORDPRESS_DB_PASSWORD: wordpress

启动

docker-compose up -d

使用

docker-compose 加下列选项

-f	        指定使用的 yaml 文件位置 必须写在log前		   up -d	    启动容器项目
ps	        显示所有容器信息			                    pause	     暂停容器
restart	    重新启动容器				                     unpause	  恢复暂停
logs	    查看日志信息				                     rm	          删除容器
config -q    验证 yaml 配置文件是否正确
stop	    停止容器
start	    启动容器

镜像、仓库管理

容器创建时需要指定镜像,每个镜像都由唯一的标示 Image ID ,和容器的 Container ID 一样,默认 128 位(镜像最多支持128层),可以使用前 16 为缩略形式,也可以使用镜像名与版本号两部分组合唯一标示,如果省略版本号,默认使用最新版本标签 ( latesr 要尽量避免使用这种版本标签,因为会下载最新版哪怕本地仓库有镜像)

镜像名:例

hub.xxhf.com/wangweijianlinux/myapp:v1
仓库地址      用户名           镜像名:版本号

镜像的分层:Docker 的镜像通过联合文件系统 ( union filesystem ) 将各层文件系统叠加在一起 (最大128层超过会报错)

bootfs:用于系统引导的文件系统,包括 bootloader 和 kernel,容器启动完成后会被卸载以节省内存资源
roofs:位于 bootfs 之上,表现为 Docker 容器的跟文件系统
传统模式中,系统启动时,内核挂载 rootfs 时会首先将其挂载为“只读”模式,完整性自检完成后将其挂载为读写模式
Docker 中,rootfs 由内核挂载为“只读”模式,而后通过 UFS 技术挂载一个“可写” 层

已有的分层只能读不能修改

上层镜像优先级大于下层镜像(写时复制 将下层文件复制到可写层 在可写层进行修改 用户看到的内容是可写层的内容)

镜像的制作

先制作基础镜像(参照基础镜像构建)或者使用官方提供的基础镜像来构建镜像

​ 容器 > 镜像

docker commit CID -t xx.xx.xx                     将启动的容器制作成为镜像   CID=容器名  xx.xx.xx=镜像名

这条命令的使用前提是镜像可以自运行

镜像自运行的两种方式

1.镜像自带自运行

2.通过Dockerfile 封装一个可以自运行镜像

FROM 未自运行的镜像
RUN touch /root/test.sh
CMD /bin/bash /root/test.sh

​ Dockerfile>镜像 (参照Dockerfile 语法)

mkdir /tmp/test                     创建干净的空目录
vim Dockerfile                      创建并编写Dockerfile文件
docker build -t wangweijianlinux:test . 创建docker镜像    加--no-cache 不调用缓存
                镜像名           所在目录 .代表Dockerfile的文件的位置  如果不在当前目录下需要指定绝对路径

注意事项 镜像层级不能超过128层 , 如果层级过多 可以通过&将RUN层级进行联立 (尽量不适用 容易造成容器运行不稳定,排错及其麻烦)

尽可能将重用性高的层级放在下部 (重用性指 经常会发生改变的 比如软件版本更换等 避免造成其他层级依赖或调用时无法使用)

两种镜像构建方式的优缺点对比

commit 优点所见即所得 不需要调试 缺点 功能性差 仅仅是对文件层级封装 不涉及元数据信息

Dockerfile 优点更能性强,缺点 编写困难 需要调试

将两种方法融合 基础镜像>编写daockerfile文件进行封装(自运行)>commit (软件运行环境-文件)- dockerfile 封装元数据信息

镜像动态化:

​ 变量

​ 初始化脚本

使用两种镜像制作方法结合制作动态化镜像

docker pull centos:7.9      #下载官方的基础镜像
mkdir test                  #创建一个新的目录后进入此目录
mkdir 1.run                 #创建干净的目录 并进入
vim Dockerfile              #创建dockerfile文件  
内容
FROM centos:centos7.8.2009
RUN touch /root/startup.sh
CMD tail -f /root/startup..sh
docker build -t wangweijianlinux/linux:7.9run .                       #制作自启动镜像
docker run --name nginx -p 指定端口 -d wangweijianlinux/linux:7.9run   #启动镜像
docker exec -it nginx /bin/bash                                       #进入容器
docker cp 文件名 镜像名:目录                                           #将文件拷贝到容器中
yum -y install gcc gcc-c++ make pcre pcre-devel zilb zilb-devel       #在容器内部安装nginx依赖软件
tar -zvxf nginx.tar                                                   #解压nginx 
./configure 检查  make && make install 编译安装
/usr/local/nginx/sbin/nginx                                           #启动nginx并外部访问
yum clean all                                                         #删除nginx安装包  清空yum缓存  
kill -QUIT $(cat /usr/local/nginx/logs/nginx.pid)                     #优雅退出
exit                                                                  #退出容器
docker commit nginx wangweijianlinux/nginx:v1.0                       #从容器保存成镜像
mkdir 2.dockerfilebild                                                #重新创建空目录
vim Dockerfile                                                        #创建dockerfile文件
#内容
FROM wangweijianlinux/nginx:v1.0
MAINTAINER wangweijian "[email protected]"
LABEL version="2.0"                                                 
#如果镜像内有很多服务 可以设置用户  如果镜像内只有一个服务那么root和普通用户没有区别
EXPOSE 80
EXPOSE 443
ENV INDEX_DATA default_data                                           #设置变量
RUN rm -rf /root/startup.sh                                           #确定root目录下没有这个文件
ADD ./startup.sh /root/startup.sh                                     #从src复制到容器内部 
WORKDIR /usr/local/nginx                                              #切换目录
RUN chomd a+x /root/startup.sh
CMD /bin/bash /root/startup.sh                                        #设置启动时执行的命令

vim startup.sh                                                        #编写启动脚本
#内容
#!/bin/bash
echo $INDEX_DATA > /usr/local/html/nginx.html
/usr/local/nginx/sbin/nginx && tail -f /usr/local/nginx/logs/access.log  
#注意启动脚本内的命令要求是幂等的命令(幂等 可以反复执行多次的命令)

docker build -t wangweijian/nginx2.0 --no-cache .                    制作nginx镜像
#(--no-cache 不调用缓存 从新制作 否则修改文件内容后制作出来的镜像和修改之前没有区别 )
docker run --name nginx --env INDEX_DATA=123 -d -wangweijian/nginx2.0  运行容器时注入变量
#(--env 注入的变量优先级要大于Dockerfile内声明的ENV 相当于替换)

(工作中可以进行逻辑梳理伪代码编写 编写完成后将代码按照逻辑写出即可)

(工作中第一次接触一个软件封装镜像时 如果时间很宽泛 可以 使用Dockerfile 进行封装 因为dockerfile文件的重用性很高

如果 时间紧张又是一次接触 尽量将基础镜像run起来 之后进行封装 相对dockerfile来讲测试调试更简单更方便)

将自己封装的镜像放进官方仓库内

访问hub.docker.com

创建用户

创建仓库存放同一类镜像 点击 create repository

harbot 企业级私有仓库

安装要求

满足一下要求才可以安装harbot

要求python 在2.7及以上版本

Docker 引擎为1.10及以上版本

Dockers-compose 为1.6.0及以上版本

安装

上传harbot压缩包

tar -zxvf 包名              
#解压后建议保留安装包 用于日后维护使用
mv harbot /usr/local        
cd /usr/local/harbot
vim harbot.cfg             
#修改配置文件  配置文件名harbot.cfg   install.sh这个安装程序会从配置文件中调取参数
#内容修改
hostname= 
ui_url_protocol = https    #协议类型 
max_job_works = 3          #最大线程数 不建议设置过高 以免占用I/O
ssl_cert =                 #证书所在路径
ssl_cert_key =             #证书所在路径
secretkey_paht = /data     #数据保存位置
#修改完成后保存退出
#创建证书
mkdir -p /data/cert 
chmod -R 777 /data/cert
openssl genrsa -des3 -out server.key 2048
opensslreq -new-key server.key -out server.csr
cp server.key server.key.org                         #复制证书文件
opensslrsa -in server.key.org -out server.key        #删除私钥密码   (有密码的情况下无法自动登录)
openssl x509 -req -days 365 -in server.csr-signkey server.key -out server.crt   #签发证书
./install.sh   #先创建证书后安装否则报错

将域名写入 housts文件(双方都要写) 浏览器访问测试 用户名admin 密码Harbot12345 生产环竟中将证书换成生效的证书

#推镜像时报错 需要添加证书信任后重新启动dicker
vim/etc/docker/daemon.json
{
"insecure-registries": ["serverip"]
}

#要求符合格式 json对象格式中 多个对象后要加逗号  最后一个后面不加逗号否则报错
#解决完证书后 要先进行仓库登录认证才能推送镜像
#docker login 私有仓库地址   

docker的网络

netns 是在 linux 中提供网络虚拟化的一个项目,使用 netns 网络空间虚拟化可以在本地虚拟化出多个网络环境,目前 netns 在 lxc 容器中被用来为容器提供网络

使用 netns 创建的网络空间独立于当前系统的网络空间,其中的网络设备以及 iptables 规则等都是独立的,就好像进入了另外一个网络一样

#查看名字空间
ip netns list
#创建好新的名字空间后内部只有一个lo网卡 状态为DOWN
# 创建虚拟网络空间
ip netns add r1

# 进入虚拟网络空间
ip netns exec ns1 bash

# 添加一对 veth 设备
ip link add veth1.1 type veth peer name veth1.2

# 将其中一块网卡放入至 ns1 网络名称空间之中
ip link set veth1.1 netns r1

# 更改网络名称
ip link set veth1.1 name eth0

# 启动网卡
ip link set eth0 up

# 设置网卡名称
ip addr add 10.0.0.11/24 dev eth0

# 启动回环网卡
ip link set lo up

原理:在虚拟机的上添加一对veth网卡 将一个veth网卡放入虚拟空间内部,实现通讯

容器网络 使用网桥

​ 联通性:

​ 容器间的访问:网桥 Docker0

​ 容器与外部访问:SNAT 通过防火墙规则进项snat转换

​ 外部与容器访问:DNAT

​ 隔离性:NameSpace-NetWork

docker run --name test --net bridge -d id   
#docker的默认网络通讯方式 网桥模式  (网桥 类似交换机的机制)
--net bridge  
#容器没有网络栈    (类似仅主机)
--net none
#使用其他容器的网络栈,Docker容器会加入其他容器的 network namespace(实际上是把两个容器放在了一个名字空间内,一个容器通过另一个容器与外部联通)  -network container:(ContainerName)
--network container  
#表示容器使用host网络,没有自己独立的网络栈。容器可以完全访问Host的网络,不完全   (类似桥接)
--network host

暴漏端口 :

#子选项的书写位置
docker run --name MyWordPress --link db:mysql -p 8080:80 -d wordpress
#将指定端口映射至主机的随机端口
-p Containerport:
#映射至指定的主机端口
-p hostpsot:Containerprot  
#映射至指定主机的随机端口
-p ip::Containerprot
#映射到指定主机的指定端口
-p ip:hostport:Containerport
#暴漏所需要的所有端口(大写P)
-P 

#查看当前容器的映射关系
docker port ContainerName

网络优化配置

对不同的网络空间进行隔离

# docker network create 创建名字空间 -d 指定驱动 bridge 网桥驱动  --subnet 指定当前网桥驱动的网段  --gateway 指定当前网桥自己的地址
docker network create -d bridge --subnet "一个网段" --gateway "网关" mybridge-network

使用linux桥接实现主机之间的通讯

#!/bin/bash
#删除ens33网卡
ip addr del dev ens33 192.168.66.11/24
#将ens33变成虚拟网桥的物理附着点
ip link add link ens33 dev br0 type macvlan mode bridge
#修改网桥地址
ip addr add 192.168.66.11/24 dev br0
#启动虚拟网桥
ip link set dev br0 up
#添加网关
ip route add default via 192.168.66.1 dev br0

扩展 :网卡混杂模式 指如果网卡的混杂模式如果被关闭 那么当前网卡拥有的IP地址才允许被访问不是这个网卡配置的IP地址不允许通过这个网卡通信 虚拟化中混杂模式一定要被打开因为一个网卡背后可能有多个不同的地址

设置容器地址分配

#将github上的代码下载到本地
git clone https://github.com/SeaYellow/pipwork.git   
#解压
tar -zxvf pipwork.tar.gz
#复制文件放到/usr/local/bin
cp -a pipwork/pipwork /usr/local/bin
#添加执行权限即可使用此工具
chmod a+x /usr/local/bin/pipwork
###使用此工具可以给容器加地址
pipework br0 test 192.168.66.200/[email protected]

!此模式相当于将容器当成虚拟机使用 与k8s的模式相冲 看情况使用只能使用一个

数据存储

数据卷的特性

Docker 镜像由多个只读层叠加而成,启动容器时,Docker 会加载只读镜像层并在镜像栈顶部添加一个读写层

如果运行中的容器修改了现有的一个已经存在的文件,那么该文件将会从读写层下面的的只读层复制到读写层,该文件的只读版本仍然存在,只是已经被读写层中该文件的副本所隐藏,次即“写时复制”机制

写时复制状态下关闭并重启容器数据不受影响 ,删除docker容器则改变的数据全部丢失

缺点 :容器间数据共享不便,存在于联合文件系统中,不易于宿主机访问,删除容器数据丢失

数据卷的意义

数据卷:一种脱离容器的生命周期以外的存储方式或目录,数据卷创建应在容器创建或启动之前,或和容器一起创建并使用

服务分类

有状态服务:将节点踢出集群一段时间再加入到集群内后,不能和其他节点保持一致的服务 :mysql

无状态服务:将节点踢出集群一段时间再加入到集群内,能继续提供服务,和其他节点保持一致的服务 (http协议、https协议大多数为无状态服务 )

中心化服务:客户端通过网络访问服务器端的服务

去中心化服务:客户端即服务器端(比特币)

docekr的运行数据存储再 /var/lib/docker/ 目录下

数据持久化

再dockerfile文件中使用VOLUME关键字指定挂载点 封装镜像后 在/var/lib/docker/volumes/ 删除容器后可以看到持久化的文件

VOLUME (指定挂载点)

设置指令,使容器中的一个目录具有持久化存储数据的功能,该目录可以被容器本身使用,也可以共享给其他容器使用。我们知道容器使用的是 AUFS,这种文件系统不能持久化数据,当容器关闭后,所有的更改都会丢失。当容器中的应用有持久化数据的需求时可以在 Dockerfile中 使用该指令

FROM base  
VOLUME ["/tmp/data"]  

这种方式持久化优点是使用镜像的默认值 启动无需操作, 缺点是不灵活

此时可以使用这种方式进行数据持久化

mkdir /data                                  #创建目录  
docker --name nginx -v /data:/zhangsan -v /root/nginx-v:/data -d 镜像名   
#  -v 选项将物理机的目录挂载到容器内部 实现较为灵活的数据持久化 
#  :前为物理机目录 :后为容器内目录 容器内目录可以不存在会自动创建
#  可以使用多个-v选项 将多个文件夹挂载到容器内部 不冲突即可
# -v可以跟文件的绝对路径  将文件挂载到容器内 例:-v /data/dockerfile:/data  此时是将dockerfile文件映射到容器内,这时/data被映射成了一个文件 如果想保留目录则需要手动递归创建目录后进行挂载

当VOLUME和-v选项相冲时以-v为准 也就是说在有VOLUME默认值的情况下使用-v选项启动的容器数据会保存在-v指定的挂载目录下

多容器之间的卷共享

docker run --name wordpress1 -d wordpress      #创建一个容器
docker run --name wordpress2 --volmues-from wordpress1 -d wordpress #--volmues-from指定wordpress2与wordpress1的卷保持一致(公用一个卷)

存储驱动

在docker分层文件系统中如果使用的是DM 或者btrfs 应将其升级为overlayfs

修改方法:

echo "overlay" > /etc/modules-load.d/overlay.conf   #将overlay关键字放在模块的加载目录下
cat /proc/modules | grep overlay                    #查看模块是否加载
reboot                                              #重载(内核要求在3.18以上)
vim /etc/systemd/system/docker.service              #打开docker的启动管理脚本
--storagt-driver=overlay \                          #在内部加入当前的主流启动引擎为overlay

overlayfs的概念 :

mkdir /overlay
cd /overlay
mkdir low                          #创建镜像层目录
mkdir upper                        #创建可写层
mkdir work                         #创建工作层
mkdir merged                       #用户挂载点
mount -t overlay overlay -olowerdir=./low,upperdir=./upper,workdir=./work ./merged   #挂载分层文件系统
#overlay文件系统可以被mount挂载直接使用的  但需要符合目录结构  
mount                            #查看挂载
#  在low文件夹内创建文件 1.txt
#  在upper文件夹内创建 2.html 
yum -y install tree                 #安装树文件系统
#对以上两个文件进行修改,使用tree查看变化

Container mount 用户展现层

Container layer 相当于可写层

image layer 相当于镜像层

结论:在镜像层创建的文件 会出现在 merged 层上 ,在可写层创建的文件同样会出现在merged层上。当修改镜像层内文件时该文件会被复制到可写层上,在可写层上被修改(即写时复制)当在用户层把在可写层内创建的文件删除时 用户层内的此文件和可写层内的此文件都会被删除 。 在用户层删除镜像层的文件时 镜像层文件并不会被删除 ,用户看不见此镜像层文件的原因是该文件在可写层 使用c 对文件进行了标记,如果要用户层重新看见镜像层的文件 将可写层内被c标记的文件删除即可。

资源限制

资源分类:

​ 可压缩资源:cpu 磁盘IO 网络IO 存储空间部分可压缩

​ 不可压缩资源: 内存

在内核的内存空间被占用的时候 会产生一种报错 OOME

OOME:内存使用量过高导致威胁内核生存 内核开始随机杀死进程以释放内存保证自己存活,一直杀到保证内核正常运行的内存空间为止。

cgrop

最低控制单位 :进程组群 (多个进程可以归为一个进程组群下 限制的最低单位是一个组群而不是单个进程)如创建一个进程组群 限制资源限制为500MB 将一个进程放进组群内 则这个进程独享进程组群所允许使用的全部500MB 如果再加入一个进程的时候则 两个进程共享进程组群的500MB资源 可以对 CPU 内存 磁盘输入输出等进行限制

功能: 限制资源使用(核心功能);优先级控制;一些审计或统计;挂起进程和恢复进程

实验:

#示例代码(c语言死循环代码) 
vim main.c            #创建C语言文件 并将下列代码写入文件内部保存退出
int main(void)
{
int i = 0;
for(;;) i++
return 0;
}
yum -y install gcc gcc-c++      #安装编译工具
gcc main.c                      #编译  会生成一个a.out文件 此文件是可执行文件
./a.out                         #运行代码
top                             #查看当前cup使用量
mount -t cgrop                 #查看cgrop挂载点
cd /sys/fs/cgrop/cpu           #文件系统映射在当前目录下 不同的子系统会有不同的目录创建出来 此时为cpu子系统下
mkdir cpu_test                 #创建子子系统
#在父子系统中 所有进程共享所有资源 在子子系统中可以对进程使用资源进行限制
echo > 进程号 /sys/fs/cgrop/cpu/cpu_test/tasks #将进程放在子子系统中运行
echo 20000 > /sys/fs/cgrop/cpu/cpu_test/cpu.cfs_quota_us #借助这个文件对资源进行限制  20000指20%
#如果想对容器进行cpu进行资源使用限制 只需要将限制配额写入/sys/fs/cgrop/docker/容器id号/cpu.cfs_quota_us内即可

内存资源限制

默认情况下如果对容器不做限制 容器能够占用当前系统能给容器提供的所有资源

docker 限制资源可以从 Memery 、CUP 、 I/O 三个方面

OOME :一旦发生OOME报错任何进程都可以被杀死 包括docker daemon

​ :为此docker 调整了docker daemon 的OOM等级 以免被内核关闭

限制选项

-m --memory   #内存限制,格式是数字加单位 b、k、m、g 最小为4M  (物理内存)
--memory-swap #此选项为物理内存+交换分区大小的总限制。格式同上
              #可能性1:--memory-swap=正数S --memory=正数M 容器可用总空间为S 其中物理内存为M swap=S-M 若S=M则无swap资源可用
              #可能性2:--memory-swap=0 --memory=正数M 相当为没设置swap
              #可能性3:--memory-swap=unset --memory=正数M 若容器启用了swap分区则容器可用的swap为两倍的物理内存但swap的使用量不能大于物理机swap分区的大小
              #可能性4:--memory-swap=-1 --memory=正数M 若物理机启用了swap分区则容器可以使用物理机上的所有的swap空间资源
              #容器内的free命令不要信
--memory-reservation #内存软限制 格式同上
--oom-kill-disable   #是否阻止oome杀死容器默认没设置 (此选项比较危险尽量不要使用)
--oom-score-adj      #设置容器被oome 杀死的优先级 范围-1000~1000 默认为0 数字越大越容易被杀死
--memory-swappiness  #用于设置容器的虚拟内存控制行为。值为0~100之间的整数 如果为0则优先使用虚拟内存 如果为100则全部使用物理内纯,在物理内存使用光后才使用虚拟内存
--kernel-memory 核心内存限制格式同上,最小为4M

cpu限制选项

默认情况下如果对容器不做限制 容器能够占用当前系统能给容器提供的所有CPU资源,大多数采用的是CFS调度算法。

docker1.13版本后支持实时调度算法

--cpuset-cpus""      #允许使用cpu的集 值可以是0-3、0、1 指将容器与cpu核心进行亲和性绑定
-c,--cpu-shares=0    #CPU共享权值(相对权重)
cpu-period=0         #限制CPU的CFS周期,范围从100ms~1s 即1000~1000000
--cpu-quota=0        #限制CPU CFS 配额,必须不小于1ms 即>1000
--cpuset-mems=""     #允许在上执行内存节点(MEMs)只对NUMA系统有效 NUMA:对称多处理器架构,内存分区尽可能减少CPU和内存的延时  如果--cpuset-cpus"0" 的情况下--cpuset-mems="1" 那么结果是可以使用全部分区内存,优点是CPU内存视图大,缺点是延时高。所以尽可能的保持--cpuset-cpus""和--cpuset-mems=""的值是一致的
--cpus               #设置能够使用的CPU核心数目  可以是小数
    例:docker run --name staress -it --rm -m 256m lorel/docker-staress-ng:latest stress -vm 2
    #启动ubantu系统压测镜像  -m 256m 限制内存使用量为256*3   -vm 开始压测 2 两个线程 原理无限创建数组
    例:docker run --name staress -it --rm --cpu 2 lorel/docker-staress-ng:latest stress --cpu8
    #启动压测cpu的镜像 ---cpu 后可以跟小数 0.2代表20%

Dcoker image Build 高级

测试环境要求 :大 包含的功能更全 测试组件更多

生产环境要求:小 在保留功能性的形况下尽可能的精简

高级镜像构建

使用场景 :尽可能将编译环境和执行环境分离的概念 c语言环境 go语言环境

镜像 Cache 机制

Docker Daemnon 通过 Dockerfile 构建镜像时,当发现即将新构建出的镜像与已有的某镜像重复时,可以选择放弃构建新的镜像,而是选用已有的镜像作为构建结果,也就是采取本地已经 cache 的镜像作为结果

Cache 机制的注意事项:

1. ADD 命令与 COPY 命令:Dockerfile 没有发生任何改变,但是命令ADD run.sh / 中 Dockerfile 当前目录下的 run.sh 却发生了变化,从而将直接导致镜像层文件系统内容的更新,原则上不应该再使用 cache。那么,判断 ADD 命令或者 COPY 命令后紧接的文件是否发生变化,则成为是否延用 cache 的重要依据。Docker 采取的策略是:获取 Dockerfile 下内容(包括文件的部分 inode 信息),计算出一个唯一的 hash 值,若 hash 值未发生变化,则可以认为文件内容没有发生变化,可以使用 cache 机制;反之亦然**

2. RUN 命令存在外部依赖:一旦 RUN 命令存在外部依赖,如RUN apt-get update,那么随着时间的推移,基于同一个基础镜像,一年的 apt-get update 和一年后的 apt-get update, 由于软件源软件的更新,从而导致产生的镜像理论上应该不同。如果继续使用 cache 机制,将存在不满足用户需求的情况。Docker 一开始的设计既考虑了外部依赖的问题,用户可以使用参数 --no-cache 确保获取最新的外部依赖,命令为docker build --no-cache -t="my_new_image" .

3. 树状的镜像关系决定了,一次新镜像的成功构建将导致后续的 cache 机制全部失效:这一点很好理解,一旦产生一个新的镜像,同时意味着产生一个新的镜像 ID,而当前宿主机环境中肯定不会存在一个镜像,此镜像 ID 的父镜像 ID 是新产生镜像的ID。这也是为什么,书写 Dockerfile 时,应该将更多静态的安装、配置命令尽可能地放在 Dockerfile 的较前位置

传统 Build 流程

FROM golang:1.7.3                                                                 
WORKDIR /go/src/github.com/sparkdevo/href-counter/                        
RUN go get -d -v golang.org/x/net/html                                    
COPY app.go .                                                           
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .   

FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY app .
CMD ["./app"] 
#!/bin/sh
echo Building sparkdevo/href-counter:build
# 构建编译应用程序的镜像
docker build --no-cache -t sparkdevo/href-counter:build . -f Dockerfile.build
# 创建应用程序
docker create --name extract sparkdevo/href-counter:build
# 拷贝编译好的应用程序
docker cp extract:/go/src/github.com/sparkdevo/href-counter/app ./app
docker rm -f extract

echo Building sparkdevo/href-counter:latest
# 构建运行应用程序的镜像
docker build --no-cache -t sparkdevo/href-counter:latest .

aa

# 下载使用的代码
$ git clone https://github.com/wangyanglinux/href-counter.git

Dockerfile 中 multi-stage

FROM golang:1.7.3                                        
WORKDIR /go/src/github.com/sparkdevo/href-counter/          
RUN go get -d -v golang.org/x/net/html                      
COPY app.go    .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/sparkdevo/href-counter/app .
CMD ["./app"]

在dockerfile文件中在17.05版本以上 可以有多个from 中间用空格隔开表示多级构建

命名方式的 stage

FROM golang:1.7.3 as builder
WORKDIR /go/src/github.com/sparkdevo/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go    .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/src/github.com/sparkdevo/href-counter/app .
CMD ["./app"]

在一个层级后面加上 as 别名 后面的层级可以根据别名直接调用

Google 内部精简镜像

$ git clone https://github.com/GoogleContainerTools/distroless

测试环境中不要使用多级构建的优化 也就是以上的流程制作镜像

你可能感兴趣的:(docker,容器,linux)