1

docker 架构

cs架构,使用客户端访问服务端client 客户端,server 服务端,接受请求处理客户端请求

  1. docker client 客户端,向服务端发起请求
  2. docker daemon 后台守护程序
    1. server 服务端
    2. engine 容器引擎,真正处理
  3. registry 镜像仓库、用户信息等

docker 安装

安装docker 要求,linux 内核版本大于3.10 ,查看内核版本方法:

1
2
3
[root@MiWiFi-CR6609-srv ~]# uname -a
Linux MiWiFi-CR6609-srv 3.10.0-1160.el7.x86_64 #1 SMP Mon Oct 19 16:18:59 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

CentOS 7(使用 yum 进行安装)

1
2
3
4
5
6
7
8
9
10
11
# step 1: 安装必要的一些系统工具
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# Step 2: 添加软件源信息,将软件源修改为阿里云
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# Step 3
sudo sed -i 's+download.docker.com+mirrors.aliyun.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo
# Step 4: 更新并安装Docker-CE
sudo yum makecache fast
sudo yum -y install docker-ce
# Step 4: 开启Docker服务
sudo service docker start

配置阿里云镜像仓库加速

容器stop之后,自动rm

1
2
3
配置 --rm 参数,stop之后自动 rm 掉容器
[root@MiWiFi-CR6609-srv ~]# docker run -d -p 80:80 --rm nginx
b8d4146001662f0dba57bde728f6e3219623ca9123b9486f9b011a65c21085b1

配置容器挂掉自动重启

1
2
3
4
5
6
7
三种策略可选:
no(默认):默认不重启
on-failure:指定自动重启次数
always:无限次重启

docker run -d -p 80:80 --restart on-failure:3 --rm nginx
docker run -d -p 80:80 --restart always --rm nginx

配置容器中的环境变量

1
2
3
4
5
6
7
docker run -d -p 80:80 -e JAVA_ENV=DEV -e JAVA_VM=G1  nginx 

检查配置好的参数
docker inspect 容器名称

打印容器中的环境变量
docker exec -it 容器名称 bash -c 'echo "$JAVA_ENV"'

资源限制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
```





# 第三章、安装使用dockers

<!--more-->

## 3.1 docker架构和底层技术

docker是一个平台platform,上层的是application应用,中间是docker Engine 引擎,底层是硬件平台,其中的docker Engine 又包括三部分 1).后台进程dockerd 2).REST API server通信 3).CLI接口docker命令行工具。

```cmd
# 查看docker客户端和服务端的版本
[root@shuoshuo ~]# docker version
Client: #客户端版本
Version: 1.13.1
API version: 1.26
Package version: docker-1.13.1-96.gitb2f74b2.el7.centos.x86_64
Go version: go1.10.3
Git commit: b2f74b2/1.13.1
Built: Wed May 1 14:55:20 2019
OS/Arch: linux/amd64

Server: #服务端版本
Version: 1.13.1
API version: 1.26 (minimum version 1.12)
Package version: docker-1.13.1-96.gitb2f74b2.el7.centos.x86_64
Go version: go1.10.3
Git commit: b2f74b2/1.13.1
Built: Wed May 1 14:55:20 2019
OS/Arch: linux/amd64
Experimental: false


# 查看docker进程
[root@shuoshuo ~]# ps -ef | grep docker
root 11056 1 0 21:12 ? 00:00:00 /usr/bin/dockerd-current --add-runtime docker-runc=/usr/libexec/docker/docker-runc-current --default-runtime=docker-runc --exec-opt native.cgroupdriver=systemd --userland-proxy-path=/usr/libexec/docker/docker-proxy-current --init-path=/usr/libexec/docker/docker-init-current --seccomp-profile=/etc/docker/seccomp.json --selinux-enabled --log-driver=journald --signature-verification=false --storage-driver overlay2

root 11061 11056 0 21:12 ? 00:00:00 /usr/bin/docker-containerd-current -l unix:///var/run/docker/libcontainerd/docker-containerd.sock --metrics-interval=0 --start-timeout 2m --state-dir /var/run/docker/libcontainerd/containerd --shim docker-containerd-shim --runtime docker-runc --debug --runtime-args --systemd-cgroup=true

root 11229 11211 0 21:15 pts/0 00:00:00 grep --color=auto docker

docker使用的一些底层技术 1). Namespace 应用隔离技术 2). contral groups 资源限制技术 3).unionfile systems 分层技术

Docker 的三大核心概念:

镜像(Image)

容器( Container )

仓库( Repository)

社区版本每个月会发布一次尝鲜( Edge )版本,每个季度( 3 、6 、9 、12 月)会发行一次稳定( Stable )版本。版本号命名格式为“年份.月份”,如2018 年6 月发布的版本号为vl8.06 。

1
2
3
4
5
6
uname  -a  #查看Linux内核版本需要高于3.1
yum update #可选更新Linux内核
yum install docker #安装docker
systemctl start docker #启动dockers
systemctl enable docker #设置docker开机启动
systemctl stop docker #关闭docker

3.2 docker image 镜像

image 由 文件和mate data组成,每一个镜像本身是只读的

1
2
3
4
5
image4
image3 image2 image1
ubuntImg centorImg debanImg #这三个都是baseImage
Linux Kemel (bootfs) #Linux内核文件系统

3.3 DIY base Image

1
2
3
4
#将当前用户添加到docker组中,以便于可以使用docker命令
sudo groupadd docker
sudo gpasswd -a vagrant docker
sudo docker restart
1
2
3
4
5
6
7
8
9
10
11
12
#官方hello-world示例
[root@shuoshuo dockert]# docker pull hello-world

[root@shuoshuo dockert]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/hello-world latest fce289e99eb9 6 months ago 1.84 kB

#运行镜像
[root@shuoshuo dockert]# docker run hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#自己创建一个image,类似官方的hello-world
#yum 查看所有安装的软件包
[root@shuoshuo dockert]# yum list installed
#安装两个需要的软件,-y 默认选中yes
[root@shuoshuo dockert]# yum install -y gcc
[root@shuoshuo dockert]# yum install -y glibc-static

#创建文件
[root@shuoshuo dockert]# vi hello-world-shuoshuo.c
# 文件内容:
#include<stdio.h>
int main(){
printf("hello word --DIV docker image\n");
}
#编译.c文件,生成一个 hello文件
[root@shuoshuo dockert]# gcc -static hello-world-shuoshuo.c -o hello
[root@shuoshuo dockert]# ll
-rwxr-xr-x. 1 root root 856792 720 21:53 hello
-rw-r--r--. 1 root root 76 720 21:53 hello-world-shuoshuo.c
# 执行hell文件
[root@shuoshuo dockert]# ./hello
hello word --DIV docker image
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 接上面,正式docker指令
# 再dockert文件夹下创建一个文件
[root@shuoshuo dockert]# vi Dockerfile
[root@shuoshuo dockert]# cat Dockerfile
FROM scratch
ADD hello / #两个参数 hello 是.c文件编译后的可执行文件 / 代表根目录
CMD ["/hello"]


#正式构建一个image,名称为shuoshuo/hello-dockert,注意最后有一个英文点
[root@shuoshuo dockert]# docker build -t shuoshuo/hello-dockert .
Sending build context to Docker daemon 860.7 kB
Step 1/3 : FROM scratch
--->
Step 2/3 : ADD hello /
---> be49755d4013
Removing intermediate container f2e4cddd38a7
Step 3/3 : CMD /hello
---> Running in efba8530587e
---> 668ed64e0e91
Removing intermediate container efba8530587e
Successfully built 668ed64e0e91

[root@shuoshuo dockert]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
shuoshuo/hello-dockert latest 668ed64e0e91 2 minutes ago 857 kB
docker.io/hello-world latest fce289e99eb9 6 months ago 1.84 kB


#运行自己的镜像,打印hello word --DIV docker image 一行华
[root@shuoshuo dockert]# docker run shuoshuo/hello-dockert
hello word --DIV docker image

3.4 容器 container

  1. 通过image创建
  2. 再image上再加一层可读可写的层,运行的时候修改的就是最顶上这一层,别的都不东
  3. Image负责存储和分发,而container负责运行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#创建container
[root@shuoshuo dockert]# docker run shuoshuo/hello-dockert
hello word --DIV docker image

#查看正在运行中的容器,一个也没有
[root@shuoshuo dockert]# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

#查看所有的容器,包括已经运行结束的
[root@shuoshuo dockert]# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9f58c6d0f2be shuoshuo/hello-dockert "/hello" 7 minutes ago Exited (30) 7 minutes ago pedantic_hopper
bb6b7dc098b9 hello-world "/hello" 27 minutes ago Exited (0) 26 minutes ago loving_bhaskara

pull一个contos镜像,进到里面去,并且在里面安装vim,

1
2
3
docker pull centos
docker run -it centos
exit #退出

删除镜像或者容器,和简写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#镜像,删除镜像前需要先删除所有产生的容器,
[root@shuoshuo dockert]# docker image rm fce289e99eb9

# 容器
[root@shuoshuo dockert]# docker container rm (容器ID,CONTAINER ID,48c4e5f4c249,02d23e56f)
[root@shuoshuo dockert]# docker rm (容器ID,CONTAINER ID,48c4e5f4c249,02d23e56f)

#批量删除容器,-q 只显示所有容器的ID
[root@shuoshuo dockert]# docker ps -aq
b1c4c8064eac
136edede57ca

#上面命令类似与下面命令只打印第一行
[root@shuoshuo dockert]# docker ps -a | awk {'print$1'}
CONTAINER
b1c4c8064eac
136edede57ca


#删除所有容器
[root@shuoshuo dockert]# docker rm $( docker ps -aq )

#打印所有未运行的容器
[root@shuoshuo dockert]# docker container ls -f "status=exited"

#删除所有未运行的容器
[root@shuoshuo dockert]# docker rm $( docker container ls -f "status=exited" -aq )

简写命令

1
2
3
4
5
6
7
[root@shuoshuo dockert]# docker container ls
[root@shuoshuo dockert]# docker ps


[root@shuoshuo dockert]# docker image ls
[root@shuoshuo dockert]# docker images

3.5 构建自己的docker镜像

通过容器构建自己的image容器,两个命令

1
2
docker container commit
可以简写成 docker commit
1
2
3
4
5
6
7
8
9
#交互环境启动docker中的centos容器
#在centos里面yun install vim 然后退出

[root@shuoshuo ~]# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
296d6710237f docker.io/centos "/bin/bash" 6 minutes ago Exited (0) 3 minutes ago adoring_curie

[root@shuoshuo ~]# docker commit adoring_curie shuoshuo/centos-vim
#命令 docker commit 容器名称NAMES 镜像名称

第二种根据image创建镜像,然后根据镜像生成属于自己的image

1
2
3
4
5
6
7
[root@shuoshuo ~]# mkdir docker-contos-vim
[root@shuoshuo ~]# cd docker-contos-vim/
[root@shuoshuo docker-contos-vim]# vi Dockerfile
FROM centos
RUN yum install -y vim
[root@shuoshuo docker-contos-vim]# docker build -t shuoshuo2/centos-vim-new2 .

3.6Dockerfile语法梳理和实践

FROM

1
2
3
4
5
FROM            #在哪个baseImage之上构建
FROM centos #使用base Image centos之上构建
FROM scratch #制作base image使用 ,helloworld没有用baseImage就from scratch
FROM ubuntu:14.04
#使用要点:尽量使用官方image作为base image

MAINTAINER

1
2
描述镜像作者,以及联系方式
MAINTAINER wolfcode<aaaa@bbbb.com>

LABEL

1
2
3
4
5
LABEL   #保留一些帮助信息,就是注释
LABEL maintainer="xxx@123.com"
LABEL version="1.0"
LABEL description = "This is description"

RUN

1
2
3
4
5
6
7
8
9
10
11
RUN #执行的代码
RUN yum install -y vim
RUN yum update && yum install -y vim python-dev
RUN yum update && \
yum install -y vim python-dev

RUN ["可执行文件","文件执行参数","文件执行参数"] # 直接调用sh文件写法

# 为了美观,复杂的RUN使用 \ 反斜线换行
# 避免无用分层,合并多头命令一行执行,中间用 && 连接
# 程序在build中使用的命令,执行的时候不会运行RUN命令

WORKDIR

1
2
3
4
5
6
7
8
WORKDIR   #改变目录
WORKDIR /test #没有则创建目录
WORKDIR demo #进入目录demo

RUN pwd #打印/test/demo

# 使用 WORKDIR,不要使用 RUN cd!!!
# 尽量使用绝对路径

VOLUME

1
2
3
4
# 镜像数据卷绑定,将主机中的指定目录挂载到容器中
VOLUME ["/roott/data/volume_1"]

# 事实上dockerfile也不允许在file中指定数据卷的挂载,如果想挂载的话在docker run命令中指定

EXPOSE

1
2
3
4
# 运行后需要暴露端口,但仅仅表示该容器想要暴露端口,并不会具体暴露出来
# 具体暴露出来需要 在 run -p 参数指定

EXPOSE 80 # 表示容器要暴露80端口,和主机没有关系

ADD and COPY

1
2
3
4
5
6
7
8
9
10
ADD and  COPY  #将本地文件添加到镜像中
ADD hello / #将本地文件添加到镜像中的 / 路径下
ADD test.tar.gz / #将文件添加到根目录并解压

WORKDIR /root
ADD hello test/ #将hello文件添加到 /root/test/目录中
ADD ["/root/data/file","/root/data/file"]
# 大部分情况下copy优于add
# add除了copy还有额外的解压功能
# 添加远程文件或者目录请使用 curl 或者 wget

ENV

1
2
3
4
5
6
ENV  #设置环境变量
ENV MYSQL_VERSION 5.6 #设置环境变量,一行一个

ENV mysql_version=5.6 JAVA_HOME=/root/data/java # 一行写多个环境变量

RUN apt-get install -y mysql-service="$MYSQL_VERSION" #RUN 命令中 引用变量

其余命令

1
2
VOLUME  和 EXPOSE  存储和网络
CMD 和 ENTRYPOINT

3.7 RUN and CMD and ECTRYPOINT

1
2
3
4
5
6
7
8
RUN 指令:用于指定 docker build 过程中要运行的命令。
语法格式:
RUN <command> 或
RUN ["<executeable>","<param1>","param2",...]
RUN ["/bin/bash","-c","<executeable>","param1","param2",...]

例如:
RUN yum install iproute nginx && yum clean all

CMD 和 ECTRYPOINT 选择一个就可以

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
CMD 指令:类似于 RUN 指令,用于运行程序,但二者运行的时间点不同;CMD 在docker run 时运行,而非docker build;
CMD 指令的首要目的在于为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束;注意: CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。
语法格式:
CMD <command> 或
CMD ["<executeable>","<param1>","<param2>",...]
CMD ["<param1>","<param2>",...] 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数;
例如:
CMD ["/usr/sbin/httpd","-c","/etc/httpd/conf/httpd.conf"]

注意:如果 dockerfile 中如果存在多个CMD指令,仅最后一个生效;
例如:

FROM centos
ENV name dockershuoshuo
CMD echo "shuoshuo,$name"

[root@shuoshuo cmd]# docker run shuo/cmd_shell
shuoshuo,dockershuoshuo
[root@shuoshuo cmd]# docker run shuo/cmd_shell /bin/bash #不打印那行话
[root@shuoshuo cmd]#


# CMD ping 127.0.0.1
# CMD ["sh", "-c", "ping 127.0.0.1"]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ENTRYPOINT 指令:类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序,让容器以应用程序或者服务的形式运行,不会被忽略,一定执行。
但是, 如果运行 docker run 时使用了 --entrypoint 选项,此选项的参数可当作要运行的程序覆盖 ENTRYPOINT 指令指定的程序;
比CMD使用的比较多
语法格式:
ENTRYPOINT <command> 或
ENTRYPOINT ["<executeable>","<param1>","<param2>",...]

例如:
CMD ["-c"]
ENTRYPOINT ["top","-b"]
最佳实践mongod安装:
COPY mong.sh /user/local/bin
ENTRYPOINT ["mong.sh"]
EXPOSE 27017
CMD ["mongod"]

shell 和 exec 两种写法的区别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
shell 格式
RUN apt-get install -y vim
CMD echo "hello docker"
ENTRYPOINT echo "hello docker"

EXEC格式
RUN ["apt-get","install","-y","vim"]
CMD ["/bin/echo","hello docker"]
ENTRYPOINT ["/bin/echo","hello docker"]

FROM centos
ENTRYPOINT echo "hello,$name" #会替换变量
ENTRYPOINT [ "/bin/echo","hello $name" ] #不会替换变量,执行echo命令,不是shell
ENTRYPOINT [ "/bin/bash","-c","echo","hello,$name"] #不会替换变量
ENTRYPOINT [ "/bin/bash","-c","echo hello $name"] #会替换变量

shell类型命令执行命令会识别$符号代表一个变量,会替换
EXEC格式打印字符串的时候,只是执行echo命令
1
2
3
4
5
6
7
8
9
10
FROM centos
ENV name dockershuoshuo
CMD echo "shuoshuo,$name"


FROM centos
ENV name shuohsuo
CMD ["/bin/echo","echo hello $name"]


补充命令

ARG

1
2
3
4
5
6
7
8
9
10
11
ARG 命令,定义一个有默认值的变量,build的时候可以录入,也可以用默认值
语法:ARG <name>[=<default value>]

dockerfile写法:

ARG jdk=1.8
FROM openjdk:$jdk

build 的时候的两种写法
docker build -t --build-arg jdk=11 # 指定版本为 11
docker build -t # 默认使用版本1.8

USER

1
用户管理

ONBUILD

1
2
3
4
5
6
7
再有另外一个镜像,基于该镜像FROM 的时候会执行的命令。
镜像A设置如下命令:
ONBUILD RUN ls -al
镜像B:
FROM 镜像A
...
构建镜像B 时,会执行 ls -al 命令

docker官网服务

1
2
3
docker longin  #登录
docker push 自己的名字/镜像名称:latest #上传
docker pull 自己的名字/镜像名称:latest #拉取

搭建私有的docker restart

1
docker run -d -p 5000:5000 --restart always --name registry registry:2
1
2
telnet 10.75.44.222 5000
yum install telnet
1
2
3
4
5
6
7
8
9
10
11
12
docker build -t shuoshuo2/centos-vim-new2      .
docker build -t 10.75.44.222:5000/hello-world . #构建镜像,准备往服务器上push
docker push 10.75.44.222:5000/hello-world
#为了防止push错误,需要增加一个配置
#创建文件daemon.json
vim /etc/docker/daemon.json
{ "insecure-registries" : ["10.75.44.222:5000"] }
#修改增加一行
vim /lib/systemd/system/docker.service
EnvironmentFile=-/etc/docker/daemon.json


3.9 Dockerfile实战

创建文件app.py内容如下

1
2
3
4
5
6
7
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "hello docker"
if __name__ == '__main__':
app.run() # 修改端口 app.run( port=80 )

执行文件app.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 安装pip
#执行wget命令提示 -bash: wget: command not found 
yum -y install wget
#安装pip
wget https://bootstrap.pypa.io/get-pip.py
# 正式安装
python get-pip.py
# 安装Flash模块
pip install flask
#运行文件
python app.py



#编写Dockerfile文件
FROM python:2.7
LABEL maintainer="Peng Xiao<soobaby@live.com>"
RUN pip install flask
COPY app.py /app/
WORKDIR /app
EXPOSE 5000
CMD ["python","app.py"]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Linux下载网站成一个本地文件
[root@shuoshuo ~]# wget http://127.0.0.1:5000
打印网站文件内容
[root@shuoshuo ~]# curl 127.0.0.1:5000
hello docker

#查看进程
ps -ef
# 查看后台运行的网站服务
[root@shuoshuo ~]# ps -ef | grep python
root 1201 1 0 09:15 ? 00:00:00 /usr/bin/python2 -Es /usr/sbin/tuned -l -P
root 1645 1594 0 09:20 pts/0 00:00:00 python app.py
root 1883 1816 0 09:31 pts/2 00:00:00 grep --color=auto python
#结束程序
kill -9 1645
1
2
3
4
5
查看build中的错误
docker run -t 中间image编号 /bin/bash

#后台运行 -d 参数
docker run -d shuo/flask-hallo-world2

3.10容器操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#进入容器内部
docker exec
docker exec -it 容器ID /bin/bash #进入容器内部的shell命令行,exit 退出
docker exec -it 容器ID python #进入容器内部python环境

exit #从容器内部退出

docker run -d --name=containerName shuo/stress #设定容器名称运行,并且设置后台运行
docker container stop 容器ID或者容器名称
docker stop 容器ID或者容器名称 #简写

docker container start 容器ID或者容器名称
docker start 容器ID或者容器名称 #简写

docker inspect 容器ID #查看容器信息
docker logs 运行中的容器ID #打印容器里面的运行信息



3.11容器实战2

给容器提供输入参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 先实验操作
下载创建ubuntu镜像,进入容器内部,运行命令,安装stress压力测试工具
apt-get update && apt-get install -y stress
# 查看软件命令安装位置
root@fdde35612edc:/# which stress
/usr/bin/stress

# 执行命令
ps -ef #查看

# stress 命令行信息
docker stress --vm 1 --vm-bytes 200M (默认256内存) --verbose (debug输出)

#查看docker容器占用内存
top 命令


# Dockerfile编写

FROM ubuntu
RUN apt-get update && apt-get install -y stress
ENTRYPOINT ["/usr/bin/stress"]
CMD [] # 用于接收参数

#启动容器的方法,
[root@shuoshuo ~]# docker run -it shuo/ubustress --vm 1 --verbose
--vm 1 --verbose 都是传递给 里面的stress命令

#设定容器内存
-m --memory bytes
--memory-swap bytes
-c --cup-shares int

#指定内存的启动方式
[root@shuoshuo ~]# docker run --memory=200M shuo/ubustress --vm 1 --verbose

#指定cpu运算的启动方式
[root@shuoshuo ~]# docker run --cpu-shares=10 shuo/ubustress --vm 1 --verbose
[root@shuoshuo ~]# docker run --cpu-shares=5 shuo/ubustress --vm 1 --verbose

3.12操作

1
2
3
4
5
docker search redis  #检索镜像
docker pull 镜像名:tag版本号 #名称:版本号
docker pull mysql #默认最新版稳定版latest版本
docker pull mysql:5.5 #指定版本
docker pull hub.c.163.com/public/ubuntu:18.04 #指定镜像仓库
1
2
3
#配置国内镜像站点加速
vi /etc/docker/daemon.json
"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn/"] #在json文件中加一句这个地址好像也错误的

查看镜像命令ls,tag,inspect三个命令

images查看本机镜像

1
2
3
4
5
6
7
8
9
10
11
docker images
输出信息包括

REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/mysql latest c7109f74d339 4 weeks ago 443 MB

REPOSITORY:名称
TAG:版本
IMAGE ID:镜像的ID(唯一标识镜像)ID相同则指向同一个镜像
CREATED:创建事件
size:镜像大小

创建镜像的带标签别名版本

1
2
3
4
5
6
7
8
9
10
11
12
docker tag 原镜像名称:原镜像版本 别名:别名版本
[root@shuoshuo ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/mysql latest c7109f74d339 4 weeks ago 443 MB

[root@shuoshuo ~]# docker tag docker.io/mysql:latest mysql:latest
[root@shuoshuo ~]# docker images

REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/mysql latest c7109f74d339 4 weeks ago 443 MB
mysql latest c7109f74d339 4 weeks ago 443 MB

配置容器自启动和

1
2
3
4
5
6
7
# 配置 docker 开机自动启动
systemctl enable docker

# 容器已经启动情况下
docker update --restart=always 容器ID或者名称
# 容器创建的时候
docker run -d --restart=always xxx

批量删除脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash
# 输入需要删除的镜像名称
del_images=('weixin' 'qq')

for i in ${del_images[*]};
do
if [ -n "docker images | grep '\<${del_images[i]}\>'|awk '{print $1":"$2}' |awk 'NR>2'"]
then
#执行后,只会保留最新的两个Docker镜像
docker images | grep '\<${del_images[i]}\>'|awk '{print $1":"$2}' |awk 'NR>2'|xargs docker rmi
else
echo "暂无可删除镜像"
fi
done

第四章、Docker Network

单机

Bridg Network

Host Network

None Network

多机网络

Overlay Network

环境准备

两台虚拟机IP分别位 192.168.205.10 192.168.205.11,两台机器可以ping通

4.2基础网络回顾

基于数据包的通讯方式,网络分层概念

ISO七层模型,TCP/IP五层模型,

IP地址 和 路由的概念,公有网络和内部私有网络

ping和telnet,

ping验证IP的可达性,ping不通有可能是防火墙阻断

telnet:服务可用性,端口可以访问

地址+端口 返回拒绝,代表服务不可达

地址+端口 返回通过,代表服务可达

ping 不通,但是80端口telnet可以达到,代表服务可以访问。

抓包工具

wire shark

4.3Linux网络命名空间

netnamespace 网络命名空间

启动一个linux

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
docker run -d --name test1 busybox /bin/sh -c "while true; do sleep 3600; done"
# busybox 非常小的Linux binbash

#再里面查看ip地址
ip a
# 容器里面的ip a 和 外面宿主机的ip a是不同的,网络是隔离的

#创建和删除networknamespace
ip netns list #查看networknamespace
ip netns delete XXx #删除newworknamespace
ip netns add test1 #创建两个
ip netns add test1

#查看信息test1 命名空间中的ip信息
ip netns exec test1 ip a

ip link #查看信息

4.4 dockers Bridge0 详解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[root@shuoshuo ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
090ac271d148 bridge bridge local
fe4bafdb7bb7 host host local
c7825e2ab4b4 none null local

bridge #Linux最重要的网络
#
[root@shuoshuo ~]# docker network inspect 090ac271d148
[
...
"Containers": {
"07a45b7c3e9de15366570f4d1b40263971c7eb790cab8b7cadb1b08bb697da55": {
"Name": "dockerTest2",
"EndpointID": "331a55ee0e90fe584eca935fbadc4469f4dad22989df88dd1a514054e0d23119",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
...
]
[root@shuoshuo ~]# ip a
#安装个软件
[root@shuoshuo ~]# sudo yum install bridge-utils
[root@shuoshuo ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242900f2f79 no veth1261a32

docker 里面两个容器如何通信,并且容器如何和外部通讯

1
docker run -d --name test2 --link test1 busybox /bin/sh -c "while true; do sleep 3600 ; done"

-p 端口映射 -p 80:80

4.8多容器复杂应用的部署

app.py 程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from flask import Flask
from redis import Redis
import os
import socket

app = Flask(__name__)
redis = Redis(host=os.environ.get('REDIS_HOST', '127.0.0.1'), port=6379)


@app.route('/')
def hello():
redis.incr('hits')
return 'Hello Container World! I have been seen %s times and my hostname is %s.\n' % (redis.get('hits'),socket.gethostname())


if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000, debug=True)

Dockerfile

1
2
3
4
5
6
7
FROM python:2.7
LABEL maintaner="Peng Xiao xiaoquwl@gmail.com"
COPY . /app
WORKDIR /app
RUN pip install flask redis
EXPOSE 5000
CMD [ "python", "app.py" ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 1 pull 启动 redis
# 不使用-p 启动redis,-d 后台启动,--name 指定名称
[root@shuoshuo pythonflastredis]# docker run -d --name redis docker.io/redis

#然后启动flask-redis python程序,使用 --link redis 连接上一个容器,使得可以之间ping通上一个容器,
# REDIS_HOST=redis 设定一个环境变量
[root@shuoshuo pythonflastredis]# docker run -d --link redis --name s-flask-redis -e REDIS_HOST=redis shuo/pythonflastredis


#进入容器
[root@shuoshuo pythonflastredis]# docker exec -it s-flask-redis /bin/bash
root@b253efbc7a02:/app# env
....
REDIS_HOST=redis #因为有这个所以可以ping通 reids那个容器
....
root@b253efbc7a02:/app# ping redis #测试redis
PING redis (172.17.0.3) 56(84) bytes of data.
64 bytes from redis (172.17.0.3): icmp_seq=1 ttl=64 time=0.365 ms
64 bytes from redis (172.17.0.3): icmp_seq=2 ttl=64 time=0.157 ms

#访问网站测试
root@b253efbc7a02:/app# curl 127.0.0.1:5000
Hello Container World! I have been seen 1 times and my hostname is b253efbc7a02.


#将python程序的5000端口暴露出来
[root@shuoshuo pythonflastredis]# docker run -d -p 5000:5000 --link redis --name s-flask-redis -e REDIS_HOST=redis shuo/pythonflastredis

1
2
3
4
#run启动容器的时候设置环境变量
docker run -d PENG=VALUE 镜像ID
#在Linux中查看环境变量
env

4.9多机器通信

python flast 部署在机器1

redis 部署在机器2上

创建两个虚拟机,之间可以互相ping通

docker-node1 192.168.205.10

docker-node2 192.168.205.11

1
2
3
4
5
6
7
8
9
10
Docker 安装mysql
docker run
-p 3306:3306 -it #端口映射
--name mysql3 #给容器起别名
-v /scy/mysql/conf:/etc/mysql/conf.d #文件挂载
-v /scy/mysql/logs:/logs
-v /scy/mysql/data:/var/lib/mysql
-e MYSQL_ROOT_PASSWORD=123456
--privileged=true
mysql
1
docker run -p 3306:3306 --name mysql -v /scy/mysql/conf:/etc/mysql/conf.d -v /scy/mysql/logs:/logs -v /scy/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d docker.io/mysql

docker run -p 3306:3306 –name mysql -v /scy/mysql/conf:/etc/mysql/conf.d -v /scy/mysql/logs:/logs -v /scy/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql

第五章、持久化机制

1
2
3
正常启动docker mysql 错误,查看日志 dokcer logs mysql1(容器名称)
#查看容器run失败的原因
docker logs 容器名称

Container容器里面写文件系统,默认会写道container layer可写层,容器删除则数据layer层也都没了,修改默认机制,将layer写到容器外面,将数据和容器隔离开,将数据写到外挂的本地文件系统中,容器被删除,数据改在。

两种数据持久化的方案

  1. 基于本地文件系统的volum

    可以再执行Docker create 或者 Docker run时,通过 -v参数将本地的目录作为容器的数据卷,这部分功能,是基于本地文件系统的volume管理.

  2. 基于plugin的Volume

    支持第三方的存储方法,比如NAS,aws

volume的两种类型

  1. 受管理的data volume,由docker后台自动创建

    加不加-v都会自动创建后台的volume

  2. 绑定挂载的volume,具体挂载位置可以由用户指定

数据持久化1:Data Volume

dicker file volume

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
docker volume ls #查看所有的持久化的文件
# 前提是Dockerfile中有写明白了文件路径
# 例如mysql的dockerfole 后面有一行是 volume /var/lib/mysql
# 所以可以在run的时候使用volume命令

#查看本地所有的volume
[root@shuoshuo dockert]# docker volume ls
DRIVER VOLUME NAME
local 4fd996ab13b3f27fdd599519d4acf1607ba588f5f3649a1d75049aa1adbd6e77
local mysqlfile

#run mysql的命令写法
#主要是 -v mysqlfile:/var/lib/mysql
# mysqlfile 是docker volume中的名字
# /var/lib/mysql 是myslq 的dockerfile中写好的路径文件
[root@shuoshuo dockert]# docker run -d -v mysqlfile:/var/lib/mysql --name mysql -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql

---------------------------------------


#创建MySQL
[root@shuoshuo ~]# docker run -d --name mysql -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql
#创建完成mysql,查看所有的volume会多一个
[root@shuoshuo ~]# docker volume ls

#查看volume信息 其中的Mountpoint 就是数据在本地存储的位置
[root@shuoshuo ~]# docker volume inspect f61f9028ccf7782fa4dd70800162a423089ef10ef667c73a5a032e1d1a8e664d
[
{
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/f61f9028ccf7782fa4dd70800162a423089ef10ef667c73a5a032e1d1a8e664d/_data",
"Name": "f61f9028ccf7782fa4dd70800162a423089ef10ef667c73a5a032e1d1a8e664d",
"Options": {},
"Scope": "local"
}
]

#删除volume
docker volume rm xxxxaaaffff


#指定mysql挂载到本地的文件目录
-v mysql:/var/lib/mysql
docker run -d -v mysql:/var/lib/mysql --name mysql -e MYSQL_ALLOW_EMPTY_SWORD=true mysql


#mysql设置密码启动
docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=123456 mysql

docker run -p 3306:3306 --name mysql -v $PWD/data:/mysql_data -e MYSQL_ROOT_PASSWORD=123456 -d mysql

数据持久化2:Bind Mounting

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
docker run -v /home/aaa:/root/aaa
# 将容器中的/home/aaa目录 挂载到 本地/root/aaa路径下面
# 实战,dockers-nginx

[root@shuoshuo docker-nginx]# pwd
/root/docker-nginx

[root@shuoshuo docker-nginx]# ll
总用量 8
-rw-r--r--. 1 root root 78 82 22:20 Dockerfile
-rw-r--r--. 1 root root 10 82 22:19 index.html

[root@shuoshuo docker-nginx]# cat Dockerfile
FROM nginx:latest
WORKDIR /user/share/nginx/html
COPY index.html index.html

[root@shuoshuo docker-nginx]# docker build -t shuo/nginx .


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 挂载.html文件演示样例
# 目录
[root@shuoshuo bindMounting]# pwd
/root/bindMounting

# Dockerfile文件内容
[root@shuoshuo bindMounting]# cat Dockerfile
FROM nginx:latest
WORKDIR /usr/share/nginx/html
COPY index.html index.html

# index主页内容
[root@shuoshuo bindMounting]# cat index.html
1237890

#执行命令
[root@shuoshuo bindMounting]# docker run -d -p 80:80 -v $(pwd):/usr/share/nginx/html --name webbindmounting shuoshuo/web2

# 遇到的问题,docker 挂载没有权限问题,CentOS7中Docker文件挂载的权限
# https://blog.csdn.net/whatwhowhere/article/details/81092214
# 添加selinux规则,将要挂载的目录添加到白名单:
# 示例:chcon -Rt svirt_sandbox_file_t /root/bindMounting
# 之后执行:docker run -i -t -v /docker /root/bindMounting --name eureka1 centos:7.5.1804


演示实例python flask框架挂载演示

1
2
3
4
5
6
export APP_SETTINGS="skeleton.server.config.ProductionConfig"
python manage.py create_db
python manage.py create_adming
python manage.py create_data
python manage.py runserver -h 0.0.0.0

Dockerfile

1
2
3
4
5
6
7
8
FROM python:2.7
LABEL maintainer="Peng Xiao<xiaoquwl@gmail.com>"

COPY . /skeleton
WORKDIR /skeleton
RUN pip install -r requirements.txt
EXPOSE 5000
ENTRYPOINT ["scripts/dev.sh"]

第六章、docker Compose 批处理

  1. 基于docker的命令行工具
  2. 通过一个yml文件定义多容器的docker应用
  3. 通过一条命令就可以根据yul文件的定义取创建或者管理多个容器

安装docker compose

1
https://docs.docker.com/compose/install/

文件名称:docker-compose.yml,版本选择version3,version2和3比较大的区别是2是单机版本的,3可以是多机器版本,其中的三大概念

  1. Services

    ​ 一个services代表一个container,可以从dockerhub直接pull下来,或者从本地Dockerfile的build出来一个image创建。
    ​ service的启动类似docker run,我们可以给其指定network和volume,所以可以给service指定network和volume的引用。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    # 从
    services:
    db:
    image: postgres:9.4
    volumes:
    - "db-data:/var/lib/postgresql/data"
    networks:
    - back-tier

    等价于:
    docker run -d
    --network back-tier
    -v db-data:/var/lib/postgresql/data
    postgres:9.4

    services:
    worker:
    build: ./worker
    links: # 用处不太大,都是使用workds
    - db
    - redis
    networks:
    - back-tier
  2. Networks

  3. Volumes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
version: "3"
services:
wordpress:
image: wordpress
ports:
- 8080:80
environment:
WORDPRESS_DB_HOST: mysql
WORDPRESS_DB_PASSWORD: root
networks:
- my-bridge
mysql:
image: mysql_wordpress
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: wordpress
volumes:
- mysql-data:/ver/lib/mysql
networks:
- my-bridge
volumes:
mysql-data:

networks:
my-bridge:
driver: bridge

docker Compose 安装和使用

1
2
3
4
https://docs.docker.com/compose/install/             #docker compose 网址

sudo curl -L "https://github.com/docker/compose/releases/download/1.2 # 下载
sudo chmod +x /usr/local/bin/docker-compose # 给可执行权限

docker compose是docker的一个命令行工具,一般情况下mac和win会一起安装

1
2
3
xshell6传递文件到虚拟机里面
[root@shuoshuo ~]# yum -y install lrzsz # 安装软件
[root@shuoshuo bin]# rz -y # 执行命令,弹出文本框,就可以选择文件上传。

docker-compose命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# docker-compose up --help
默认的文件名是 docker-compose.yml,也可以指定

docker-compose -f docker-compose.yml up
docker-compose up
docker-compose up -d #-d 后台运行的参数


#停止
docker-compose stop

#启动
docker-compose start

#停止并且删除
docker-compose down


#查看images
[root@shuoshuo docker_compose]# docker-compose images
Container Repository Tag Image Id Size
---------------------------------------------------------------------------------
docker_compose_mysql_1 mysql latest c7109f74d339 422 MB
docker_compose_wordpress_1 docker.io/wordpress latest d4f29e1a3462 478 MB

#进入容器里面
docker-compose exec mysql bash
#退出
exit

演示样例2 python+redis

1
2
3
4
5
6
7
8
9
10
11
12
version: "3"
services:
redis:
image: redis
web:
build:
context: .
dockerfile: Dockerfile
ports:
- 8080:5000
environment:
REDID_HOST: redis

第七章、Swarm Mode 容器编排

节点角色

  1. Manager管理节点,Manager之间数据同步使用分布式的存储数据库,使用Raft协议实现同步,保证Manager节点之间数据是同步的
  2. Worker 实际的工作的节点,worker之间数据同步使用Gossip network网络来实现

service和Replicas

service和docker compose 里面的service意思基本一样,但是在replicas模式下横行做扩展的时候,一个replicas就是一个容器例如一个service是nginx,要给他做三个扩展,三个容器,会通过调度系统把他调度到不同的node上面,也就是通过swarm manage去部署一个service的时候,其实是不知道service会最终运行在哪些service 节点上面的,这个会有service 使用调度算法进行计算,例如哪些节点内存和cpu使用较少,则将服务部署在这个节点上

7-2创建一个三节点的swarm集群

1
2
3
docker swarm init --advertise-addr=192.168..  #当前自己的IP,这个节点会称为Manage节点
会打印出来一些内容例如下面,只需要将中间的docker swarm join...2377之间的文本复制到别的容器中执行就可以。别的linux主机就会称为一个子节点,

1
2
3
4
5
6
7
8
$ docker swarm init --advertise-addr=192.168.0.48
Swarm initialized: current node (hhn2giwdrtuv4swp2y3lrvund) is now a manager.

To add a worker to this swarm, run the following command:

docker swarm join --token SWMTKN-1-69rmn2ok6xbp5jj37fsmuiw9ump5e4f2ao32t8eh2e1n1sgj0m-ek3g85keoan1sj7cqwlm7xiqc 192.168.0.48:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

主节点查看自己所有的子节点的命令,子节点无法使用

1
docker node ls   #查看当前swarm节点

使用docker play在新学习docker

1
网址:https://labs.play-with-docker.com/

7.3Service的维护和水平扩展

主要会介绍一个service的概念。service就类似与一个container容器,使用swarm启动容器的时候,可能会将service部署到任何一个节点上。

使用swarm创建一个service

1
2
3
命令:docker service
docker servcice create
在swarm模式下不要使用docke run,docker run是在本地创建一个container,在swarm中创建容器的时候,不一定会运行在本地

在swarm模式中启动一个容器

1
docker service create --name demo busybox sh -c "while true;do sleep 3600;done"

查看所有运行的容器

1
docker service ls

查看service的详细信息,以及在哪台机器上运行

1
2
docker service ps [容器名称]
docker service ps demo

查看swarm中运行的容器

其中REPLICAK 1/1代表可以横向扩展

将一个容器水平扩展成五个容器

1
2
3
docker service scale demo=3
docker service ls
5/5 代表五个容器都在运行

强行删除某个节点上的容器

1
2
3
docker rm -f 容器ID
docker service ls #查看容器的数量,会发现自动重启了
docker service ps demo

7.4在swarm集群中通过service部署wordpress

使用组件一个mysql和wordpress。

swarm模式下mysql和wordpress随机部署在不同的机器上,为了让他们之间相互通信,需要先手动构建一个network overlay。

1
2
3
4
docker network create -d overlay demo 
网络名称为demo
docker network ls
查看网络信息

创建mysql

1
docker service create --name mysql --env MYSQL_ROOT_PASSWORK=ROOT --env MYSQL_DATABASE=wordpress --network demo --mount type=volume,source=mysql-data,destination=/var/lib/mysql mysql

查看musql在那里

1
docker service ps mysql

安装wordpress

1
docker service create --name wordpress -p 80:80 --env WORDPRESS_DB_PASSWORD=root --env WORDPRESS_DB_HOST=mysql --network demo wordpress

7.5集群服务间通信

7.6RoutingMesh之Ingress负载均衡

搜索 lvs keepalived配置高可用负载均衡

JAVAWEB