赞
踩
先聊历史:
虚拟机的优点:
虚拟机的局限性:
容器技术为什么会出现?
容器被称为“集装箱”,它能够将App进行打包,然后能够用于任何环境,类似于现实中的集装箱。
什么是容器?
容器和虚拟机的区别?
Docker-容器技术的一种实现:
Docker它是利用了LXC的包装,然后在其基础上开源,成为了一种广泛流行的容器技术,而这种技术不止Docker一种。
Mac上是一个Unix系统。
下载并安装:
点击安装后并重启,然后在Windows桌面打开CMD窗口
docker version
可能个别同学的不一定能够安装成功,因为每个人的windows环境不是一样的。
安装步骤百度。安装成功后,输入“vagrant --help”可以看支持哪些参数。
vagrant --help
vagrant init centos/7
vagrant up
vagrant ssh
exit
vagrant status
vagrant halt
vagrant destroy
为什么不使用VM ware?
安装步骤:
准备:
进入机器:
vagrant ssh
卸载旧版本Docker:
安装Repository:
添加repo:
install docker-ce:
sudo yum install docker-ce
启动docker:
sudo systemctl start docker
校验版本:
sudo docker version
校验是否安装成功-- 运行hello,world:
sudo docker run hello-world
官网:
介绍:
安装命令:
$ base=https://github.com/docker/machine/releases/download/v0.16.0 &&
curl -L $base/docker-machine-$(uname -s)-$(uname -m) >/tmp/docker-machine &&
sudo mv /tmp/docker-machine /usr/local/bin/docker-machine &&
chmod +x /usr/local/bin/docker-machine
$ base=https://github.com/docker/machine/releases/download/v0.16.0 &&
curl -L $base/docker-machine-$(uname -s)-$(uname -m) >/usr/local/bin/docker-machine &&
chmod +x /usr/local/bin/docker-machine
$ base=https://github.com/docker/machine/releases/download/v0.16.0 &&
mkdir -p "$HOME/bin" &&
curl -L $base/docker-machine-Windows-x86_64.exe > "$HOME/bin/docker-machine.exe" &&
chmod +x "$HOME/bin/docker-machine.exe"
常用命令:
docker-machine version
一般情况下是跟着一起安装成功的。
docker-machine create --driver virtualbox test
docker-machine ip test
docker-machine stop test
docker-machine start test
docker-machine ssh test
下载并点击安装:
配置环境变量(地址为实际安装位置):
搜索Windows ProwerShell并打开
输入命令查看是否有反应:
docker-machine
展示此界面说明安装成功:
创建一个docker:
docker-machine create demo1
创建一个docker名为demo1的
创建一个Linux机器:
创建好机器后会已经自动创建好docker
登录后台界面:
参考官方教程:
进入菜单:
进入Security Credentials:
查看和创建AccessKey:
创建:
拷贝命令并创建:
需要先创建Docker Id,然后在图二上进行使用。它是一个临时的实例。
Docker Platform:
Docker Engine:
Docker Architecture:
底层技术支持:
实验环境搭建:
这个是用来练习的,可以忽略。
什么是Image?
示例:
image创建示例:
从远处拉取
远程仓库:
第三方的:
把当前用户添加进groupadd. 如果关闭还是不行,则先exit,再重新连接这个服务器。
sudo yum install gcc
sudu yum install glibc-static
gcc -static hello.c -o hello
./hello
打印出:“hello docker”
vim Dockerfile
FROM scratch
ADD hello /
CMD ["/hello"]
docker build -t anyu/hello-world .
. 表示在当前目录
docker run anyu/hello-world
打印内容: “hello docker”
什么是Container?
Container支持读写,它负责运行App。我们基于镜像运行的程序是一个Container,在里面我们能够创建文件夹、进行创建其他的东西(构建对象),然后能够将它打包成一个新的镜像(类)。
删除Container:
docker container ls -aq 等价于 docker container ls -a | awk {‘print$1’} 只是第二个带了个头部CONTAINER标识。
docker commit anyu tagdemo/image-name
anyu 表示已存在的container 的Name, tagdemo表示新建的镜像的tag, image-name表示镜像的名称。
vim Dockerfile
FROM centos
RUN yum install -y vim
docker build -t dockername/imagename .
dockername是docker名字,你可以自己设置, imagename是镜像名称,可以自己设置;.这个“点”表示当前目录,说明Dockerfile在执行命令当前目录层级中。
FROM (最开头的语法)
FROM =》尽量使用官方的,保证安全
LABEL (描述信息: 包括作者、版本、描述等)
LEBEL/Metadata 不可少!
RUN (运行):
为了美观,复杂的RUN请用反斜线换行!避免无用分层,合并多条命令成一行!
WORKDIR(设置当前目录)
使用WORKDIR ,不要用RUN cd!尽量使用绝对目录!
ADD and COPY (解压缩等):
大部分情况,COPY优于ADD! ADD除了COPY还有额外功能(解压!)添加远程文件/目录请使用curl或者wget!
ENV:
上面定义,下面引用。这样能够做到统一管理,对于版本等,可以统一设置和修改。
VOLUME and EXPOSE
存储和网络后面单独讲
CMD and ENTRYPOINT
后面单独讲
总体介绍:
CMD 和 ENTRYPOINT要注意区分,他们很接近。
Shell和Exec格式:
两种格式的Dockerfile:
CMD:
ENTRYPOINT:
Docker Hub:
分享docker image的话,不如分享Dockerfile,这样能够更安全和有隐私性。我们可以在Docker Hub中链接Github,然后只维护Dockerfile,然后Docker会自动帮我们构建镜像。
搭建一个自己私有的Docker Registry
docker run -d -p 5000:5000 --restart always --name registry r^Cistry:2
docker ps
telnet 如果没有的话,则通过yum进行安装
sudo vim /lib/systemd/system/docker.service
增加标记处这个代码
sudu service docker restart
docker push ip:5000/hello-world
hello-world替换为你自己要push的镜像
ip:5000/v2/_catalog
,如图所示:vim Dockerfile
docker build -t anyu/flask-hello-world .
docker image ls
docker run anyu/flask-hello-world
docker run -d anyu/flask-hello-world
图示:
进入bash后输入exit退出,container还是会继续运行。如果要container停止,则用
docker stop
命令,只有停止了的container,才能用删除命令;
对于启动的镜像,我们可以指定一个名字,如果不指定名字则docker会为我们随机分配一个名称;
docker查看日志输出:
docker logs $containerID
docker查看详细信息(创建时间、参数、详细信息等):
docker inspect $containerID
--vm 1 --verbose^C
命令在外部启动docker时使用,它替换掉了CMD后面的[]的内容。我们也可以在[]内给一个默认命令。
设置内存大小:
docker run --memory=200M anyu/ubuntu-stress --vm 1 --verbose
memory是设置内存大小,后面是打印的vm信息;
指定cpu个数:
docker run --cpu-shares=5 --name=test anyu/ubuntu-stress --cpu 1
按照权重的,权重值越大则CPU占比越高
基于数据包的通讯方式:
网络的分层:
IP地址和路由:
公有IP和私有IP:
网络地址转换NAT:
Ping和telent:
先保证ip可达,再保证服务可达。因为服务可达是建立在ip可达的基础上嘚。
WIRESHARK: 抓包工具,如图所示:
-
命名空间(Linux namespace)是linux内核针对容器虚拟化映入的一个特性
Linux 内核提供了6中命名空间:
网络命名空间:
查看当前网络接口:
ip a
打印指定Docker应用的网络地址:
netns常用命令:
Linux Network Namespace:
sudu docker network ls
概念:
使用方式如下:
docker run --name mysql01 -e MYSQL_ROOT_PASSWORD=123456 -d mysql
上面通过传递环境变量MYSQL_ROOT_PASSWORD=123456,来设置mysql服务的密码为123456.
docker run -d --name web --link mysql01:aliasdb nginx
上面通过 --link 连接名为 mysql01 的容器,并为其设置了别名 aliasdb
完成了上面的两个步骤后,在 nginx 的容器中就可以使用 mysql01 或者 aliasdb 作为连接地址来连接mysql服务,即使容器重启了,地址发生了变化,不会影响两个容器之间的连接。
sudo docker network inspect bridge
sudo docker run --name $name-d -p port:port $dockerName
网络除了bridge外还有host和none:
Docker 安装时会自动在host上创建三个网络,我们使用
docker network ls
命令查看。
none网络:
docker run -it --network=none busybox
封闭意味着隔离,一些对于安全性要求高的并且不需要联网的应用可以使用none网络,比如某个容器的唯一用途是生成随机密码,就可以放到none网络中避免密码被窃取。
host网络:
docker run -it --network=host busybox
bridge网络:
user-defined网络:
以太网最初设计的时候就是一个分布式的网络架构,没有中心控制节点,网络中的节点通过协议传递学习网络的可达性信息。underlay就是数据中心场景的基础物理设施,保证任何两个点路由可达,其中包含了传统的网络技术。
overlay是在网络技术领域指的是一种网络架构上叠加的虚拟化技术模式,Overlay网络也是一个网络,不过是建立在Underlay网络之上的网络。overlay网络节点通过虚拟或者逻辑链路进行通信,其实现基于ip技术的基础网络为主。Overlay网络技术多种多样,一般采用TRILL、VxLan、GRE、NVGRE等隧道技术。
提到overlay是近几年数据中心为网络兴起的概念,但是对于传统网络而言实际上早一些类似概念。
Container Layer:
Data Volume:
Docker 持久化数据的方案:
Volume的类型:
Data Volume 数据卷:
Docker的理念之一:
数据卷的设计的目的:在于数据的永久化,它完全独立于容器的生命周期,因此,Docker不会在容器删除时删除其挂载的数据卷,也不会存在类似垃圾收集机制,对容器引用的数据卷进行处理了;
数据卷特点:
使用数据卷的命令可百度,此处不赘述。
Bind Mounting 的使用只需要将本地目录和要持久化的目录进行绑定即可,命令:
docker run -v /home/aaa:/root/aaa
Data Volume 需要在Dockerfile内声明需要创建的volume目录,Bind Mounting是在run时声明。
特点:
构建并运行容器:
删除容器:
docker rm -rf flask
这里删除是为了重新运行容器并同时挂载Mouting,持久化文件。
构建新的container:
docker run -d -p 80:5000 -v $(pwd):/skeleton --name flask anyu/flask-skeleton
80宿主机绑定了docker内的5000端口;同时挂载 $(pwd)是指当前目录, 挂载到 skeleton目录下。
修改挂载的文件夹内的代码:
刷新后查看网页,发现内容已经变更为最新的代码:
我们可以很方便的根据这个特性去调试,并且它在生产环境里面可以关联着后端、mysql、redis等其他系统及工具,同时也是我们devops的第一步。
docker pull wordpress
docker pull mysql
docker run -d --name mysql -v mysql-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=wordpress mysql
docker run : 启动; --name mysql 命名容器为mysql; mysql-data:/var/lib/mysql 持久化存储至var/lib/mysql目录下; MYSQL_ROOT_PASSWORD 用户名是root,密码也是root; MYSQL_DATABASE 数据库库名为wordpress ; mysql 最后这个表示镜像名称,运行的指定的镜像是mysql;
docker run -d -e WORDPRESS_DB_HOST=mysql:3306 --link mysql -p 8080:80 wordpress
运行wordpress,并且与mysql进行关联,将wordpress的80端口与主机的8080端口绑定 ;
多容器的App太恶心
Docker Compose “批处理”
Docker Compose
所以最关键的就是这个yml文件
docker-compose.yml(三大概念)
Services:
Volumes:指定持久化目录
network:定义网络
代码示例:
通过docker-compose可以批量对container进行管理
安装docker compose:
docker-compose -version
sudo curl -L https://github.com/docker/compose/releases/download/1.18.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version
使用注意点:
docker-compose up
能够启动yml里面的全部文件docker-compose ps
能够打印启动的全部containerdocker-compose stop
所有一起停止docker-compose start
启动docker-compose down
删除里面所有的container。(但是它不会删除本地的镜像)docker-compose up -d
后台运行,如果需要实时查看日志等,可以不加 -d
docker-compose images
查看docker-compose使用的所有镜像docker-compose exec mysql base
能够进入mysql的容器里面(这里的mysql可以替换成其他你自己的container名称)redis 的docker-compose.yml代码示例:
docker-compose.yml在启动时,会先构建网络,然后创建镜像,最后再安装顺序先后执行里面的脚本代码创建container;
所以如果我们要水平扩展一个container,我们必须要先安装一个负载均衡器,再使用此命令,同时,应该切断container与宿主机的直接绑定关系,避免端口被占用。用户先访问宿主机,然后再将流量分配到各个水平扩展的container上,所以负载均衡器与container进行绑定。
web=3 就会新建3个 -d是后台运行 --scale就是水平扩展的意思。 web=10就会从3个变成10个,当不需要那么多的时候也可以减少,将web=10改成更小的数字(实际业务场景:用户访问峰值变高,可以增加container,访问变少可以减少container)
docker-compose的scale是单机上的,很多时候场景并不适合,我们大部分情况需要多机器情况下进行,后面我们会将容器编排。
Swarm项目正是这样,通过把多个Docker Engine聚集在一起,形成一个大的docker-engine,对外提供容器的集群服务。同时这个集群对外提供Swarm API,用户可以像使用Docker Engine一样使用Docker集群。
所以我们需要一个容器编排系统,去多机器的批量管理容器。
只要我们安装了docker就安装了Swarm(已内置,不需要安装其他额外的东西),只不过我们平时是运行在单机的模式下。它是我们初学者第一个接触的容器编排工具。
有三种方式:
使用Vagrantfile
vagrant ssh swarm-manager
docker swarm --help
,然后展示的内容如图所示:docker swarm init --help
查看初始化有哪些参数:docker swarm init --advertise-addr=192.168.205.10
第一个初始化的节点是我们的swarm manager节点,所以我们要先在要manager的节点上进行初始化。
exit
vagrant ssh swarm-worker1
vagrant ssh swarm-manager
docker node ls
vagrant ssh swarm-worker2
sudo service docker start
走到这里,三个节点都创建成功了。这里是一个manager,两个worker。
使用docker-machine与Paly with docker 的方式搭建与Vagrantfile类似,实际上就是三台主机,然后分别运行一个manager、两个worker命令即可。
docker service
使用此命令可以看到它下面的所有可使用命令,如图所示:
docker service create [OPTIONS] IMAGE [COMMAND] [ARG...] [flags]
):docker service create --name demo busybox sh -c "while true;do sleep 3600;done"
demo是container的名称,busybox是镜像, sh -c 是里面要执行的脚本内容;
docker service ls
使用此命令来检查刚才创建的demo 的container是否运行成功;如图所示:
docker service ps demo
使用此命令可以打印出demo container的运行状态、名称、ID、使用镜像名、端口、节点(即哪台服务器上),这里的demo可以替换成你自己的container名称;
docker ps
查看是否存在此container。如图所示:docker service scale demo=5
这个scale 跟上一章节的水平扩展一样,支持扩展和缩容,如果=5个就建5个container,如果=1个就改为运行1个container。同时如果有任意一个container宕机了,docker service 还能监测到并且重启启动一个以保持预计的数量;
docker service ps demo
启动五个,它分别在manager/worker1/worker三台服务器(虚拟机)上运行了demo 的container,以使总数达到5个。
docker service rm demo
在manager服务器节点上调用删除方法能够一次性删除全部的已注册container。(避免了登录每台服务器然后一个一个的删除)
docker service 的命令是在manager节点所在的服务器上运行的。
docker network create -d overlay demo
docker network ls
出现使用镜像overlay 的名称为demo 的container 则表示步骤1创建成功
docker service create --name mysql --env MYSQL_ROOT_PASSWORD=root --env MYSQL_DATABASE=wordpress --mount type=volume,source=mysql-data,destination=/var/lib/mysql mysql
docker service create --name wordpress -p 80:80 --env WORDPRESS_DB_PASSWORD=root --env WORDPRESS_DB_HOST=mysql --network demo wordpress
docker service ps wordpress
docker service 的命令是在manager节点所在的服务器上运行的。
sudo iptables -nl -t nat
endpoint_mode:(指定swarm服务发现的模式)
version: "3.3"
services:
wordpress:
image: wordpress
ports:
- 8080:80
networks:
- overlay
deploy:
mode: replicated
replicas: 2
endpoint_mode: vip
mysql:
image: mysql
volumes:
- db-data:/var/lib/mysql/data
networks:
- overlay
deploy:
mode: replicated
replicas: 2
endpoint_mode: dnsrr
volumes:
db-data:
networks:
overlay:
LABELS(指定服务的标签。)
version: "3"
services:
web:
image: web
deploy:
labels:
com.example.description: "This label will appear on the web service"
version: "3"
services:
web:
image: web
labels:
com.example.description: "This label will appear on all containers for the web service"
主要是设置一些帮助和描述信息
MODE(扩展模式)
global
,一种是replicated
.默认的配置是replicated
,我们一般不经常去设置它。使用global
命令则不能对容器应用进行横向扩展。global
的意思是全局,即每个集群节点只有一个容器。replicated
的意思是副本,指定容器的数量。version: '3'
services:
worker:
image: dockersamples/examplevotingapp_worker
deploy:
mode: global
PLACEMENT(指定约束和偏好设置)
version: '3'
services:
db:
image: postgres
deploy:
placement:
constraints:
- node.role == manager
- engine.labels.operatingsystem == ubuntu 14.04
preferences:
- spread: node.labels.zone
比如node.role == manager,则此容器创建只会在manager节点上进行创建。
REPLICAS(如果服务时副本模式(默认模式),可以指定该服务运行的容器数量)
version: '3'
services:
worker:
image: dockersamples/examplevotingapp_worker
networks:
- frontend
- backend
deploy:
mode: replicated
replicas: 6
这里的replicas设置为了6个,则它在一开始进行部署时,就会默认创建6个container。它就是sacle命令的默认配置;
RESOURCES(资源限制配置)
version: '3'
services:
redis:
image: redis:alpine
deploy:
limits:
cpus: '0.50'
memory: 50M
reservations:
cpus: '0.25'
memory: 20M
代码中limits里面设置了(上限)cpu和内存的最大限制数量、而reservations里面则对此容器保留(拥有)了多少cpu性能和内存大小。
RESTART_POLICY(配置在容器退出时是否并如何重启容器)。取代restart指令
version: "3"
services:
redis:
image: redis:alpine
deploy:
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s
condition:要不要重启,重启的条件是什么。delay延迟。max_attempts最大重启次数。
UPDATE_CONFIG(配置服务如何升级)
version: '3.4'
services:
vote:
image: dockersamples/examplevotingapp_vote:before
depends_on:
- redis
deploy:
replicas: 2
update_config:
parallelism: 2
delay: 10s
order: stop-first
配置更新时的一些原则
depends_on(表示服务之间的依赖关系)
version: '3'
services:
web:
build: .
depends_on:
- db
- redis
redis:
image: redis
db:
image: postgres
dns(自定义DNS服务器,可以是单个值或列表)
dns: 8.8.8.8
dns:
- 8.8.8.8
- 9.9.9.9
dns_search
dns_search: example.com
dns_search:
- dc1.example.com
- dc2.example.com
environment(添加环境变量。您可以使用数组或字典。任何布尔值;真/假,是/否,需要用引号括起来以确保它们不被YML解析器转换为True或False)
environment:
RACK_ENV: development
SHOW: 'true'
SESSION_SECRET:
environment:
- RACK_ENV=development
- SHOW=true
- SESSION_SECRET
expose(开放容器的端口而不用在主机上暴露端口,它们只能被相关联的服务获取。只能指定内部端口)
expose:
- "3000"
- "8000"
先看一下以前的docker-compose.yml文件内容:
改造网路,将bridge。
在Swarm中,容器可能分布在不同的机器上,要将bridge改为overlay。
为mysql增加Stack相关的设置:
为wordpress增加Stack相关的设置:
进入到服务器,查看Docker stack相关支持的命令:
docker stack
update_config
删除order配置后的内容:docker stack deploy wordpress --compose-file=docker-compose.yml
自动加了一个wordpress的前缀
docker stack ls
docker stack ps wordpress
docker stack rm wordpress
docker-compose.yml之前可以使用build命令,这种方式是不能使用了。
什么是Secret?
Docker Secret的架构: Docker Searm Mode Architecture
Secret Management
在指定文件使用Secret:
若不存在此文件可在docker-compose.yml中设定创建:
实战测试:
vim password
p@ssw0rd
docker secret create my-pw password
rm -rf password
docker secret ls
命令可以查看secret是否创建成功,如图所示:echo "p@ssw0rd" | docker secret create my-pw2 -
p@ssw0rd
是我们在线创建的密码。
常用secret命令:
docker secret COMMAND
docker secret rm my-pw2
其中
my-pw2
是被删除的secret名称
在Docker Service中使用secret:
docker service create --name client --secret my-pw busybox sh -c "while true; do sleep 3600; done"
这里面使用了名称为
my-pw
的secret
docker service ps client
docker ps
docker exec -it ccee sh
ccee
是具体的容器名称。
cd /run/secrets/
cat my-pw
总的来说就是docker service执行时选择指定的secret,然后在容器内部的run/secrets目录中可以找到这个文件。而且传入的时候,也可以传入多个;
实战案例–mysql中使用secret:
docker service create --name db --secret my-pw -e MYSQL_ROOT_PASSWORD_FILE=/run/secrets/my-pw mysql
docker service ls
docker service db
这个db是指上面创建的容器,如果你的容器不叫这个,相应替换即可。
vagrant ssh swarm-worker1
如果不是用vagrant创建的服务器,直接用你的方式进入即可。这里的swarm-worker1代指服务器名称
docker ps
docker exec -it $容器id sh
ls /run/secrets
mysql -u root -p
ls /run/secrets
中指定的secret内的密码内容,然后发现能够成功登录mysql,说明secret配置成功!这个案例就是将secret作为mysql的密码,在容器一开始运行的时候进行了设定。只有拥有linux中有此容器访问权限的人才有可能知道密码是什么,也就才能登录这个mysql了。
我们开发人员先在本地进行编写代码,然后可以用容器模拟生产环境做本地测试,测试通过后将代码提交至主分支,然后持续集成CI,自动构建Docker镜像,再持续部署CD,在云服务器上自动创建或更新服务。
步骤如下:
1. 绑定代码:
Docker Swarm与Kubernetes一起作为一种容器编排的解决方案:
Kubernetes Master(k8s集群的大脑)的模块:
Kubernetes Node:
k8s集群:
127.0.0.1
或者socket通信apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: java
image: a13552821243/java-demo
imagePullPolicy: IfNotPresent
如果拉取公开的镜像,直接按照上述示例即可,但要拉取私有的镜像,是必须认证镜像仓库才可以,即docker login,而在K8s集群中会有多个Node,显然这种方式很不方便的。为了解决这个问题,k8s实现了自动拉取镜像的功能。以secret方式保存到K8s中,然后传给kubelet.
spec.containers[].resources.limits.cpu
spec.containers[].resources.limits.memory
spec.containers[].resources.requests.cpu
spec.containers[].resources.requests.memory
apiVersion: v1
kind: Pod
metadata:
name: web
spec:
containers:
- name: java
image: a13552821243/java-demo
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: java
image: a13552821243java-demo
restartPolicy: Always
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness
image: busybox
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 60
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
上述示例,启动容器第一件事创建文件,停止30s,删除该文件,再停止60s,确保容器还在运行中。验证现象:容器启动正常,30s后异常,会restartPolicy策略自动重建,容器继续正常,反复现象。
一周左右完善~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。