docker 总结

docker 基本

docker 基本介绍?

docker 是一个开源的应用容器引擎,基于go语言开发,使用docker可以快速构建一个程序运行环境。使应用程序能够在独立的容器内运行。

官方网站: https://docs.docker.com/

docker 文档 https://docs.docker.com

docker hub地址 https://registry.hub.docker.com/

docker hub 类似于github 或maven 仓库的概念,是一个远程仓库,允许我们从远端仓库拉取一个镜像到本地运行

docker 对比虚拟机

相同点:
都起到了隔离运行环境的作用。
每个容器是相互隔离的,相互之间不影响

不同点:
传统虚拟机,虚拟一个操作系统,在这个系统上安装和运行软件,是比较重量级的;
容器内的应用直接运行在宿主机的内部,容器是没有自己的内核,没有虚拟硬件,是轻量级的,性能更加的好

启动 – docker 秒级 – vm 分钟级
硬盘使用 –docker MB – vm GB
性能 – 接近原生 – 弱
系统支持量 –单机上千个 – 单机几十个

使用docker的好处

  1. 消除环境的差异, 解决本地运行环境和测试,生产等环境的运行差异化。
  2. 快速构建运行环境,通过命令或编写运行文件快速构建出程序运行依赖的环境
  3. 方便升级和扩缩容
  4. 更高效的利用计算资源

docker 的概念

镜像image: 镜像就是一个模板文件,通过这个模板可以创建多个容器。

容器container: 使用镜像可以创建一个或多个容器,使用镜像文件可以创建容器。

仓库repository:仓库是集中化管理镜像的一个远程或本地仓库.

架构图:

安装和卸载

docker安装

相关链接 https://docs.docker.com/engine/install/centos/

centos7 环境

  1. 卸载旧的版本(如果有的话)
1
2
3
4
5
6
7
8
9
10
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine


  1. 安装yum工具包
1
2
yum install -y yum-utils

  1. 设置yum的仓库
1
2
3
4
5
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

//更新缓存
yum makecache fast

这里添加docker 相关的yum源添加阿里云镜像站

  1. 安装docker
1
2
3
4
5
6
7
yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io

示例:

yum install docker-ce-18.03.0.ce docker-ce-cli-18.03.0.ce containerd.io


yum list docker-ce –showduplicates | sort -r 命令查看可用版本 版本号为 冒号后 横杠前为版本号

ce 代表的是社区版, docker-ce 是社区版 docker-ee 是企业版 版本号说明 参考链接https://docs.docker.com/engine/release-notes/

  1. 启动和helloword
1
2
3
4
5
//启动服务
systemctl start docker
//执行helloword
docker run hello-world

  1. 其他加速配置

    配置镜像加速服务

    1
    2
    3
    4
    5
    cat > /etc/docker/daemon.json << EOF
    {
    "registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"]
    }
    EOF

    重启:

    // systemctl daemon-reload 
    // systemctl restart docker
    

docker卸载

1
2
3
4
5
6
yum remove docker-ce docker-ce-cli containerd.io

sudo rm -rf /var/lib/docker

sudo rm -rf /var/lib/containerd

命令

基本命令

  • docker version 显示版本号

  • docker info 当前信息

  • docker 命令 -help 查询命令帮助

  • ctrl+p+q (退出交互命令。但是不退出进程)

镜像命令

  • docker images (列出镜像)

  • docker images -a (列出所有的) -q (–quiet)只显示id

  • docker seach xx (搜索镜像,搜索列表中 列分别为 名称,描述,收藏,是否官方,是否自动)

  • docker pull:version (注意version需要在dockerhub 上存在的版本)

  • docker pull 使用分层拉取机制,不同的版本不用全量下载,只需要增量或差异下载即可

  • 删除镜像
    docker rmi id1 id2 id3
    docker rmi $(docker images -aq) 删除所有的,通过将命令作为参数

容器命令

  • 运行 docker run [参数] image
    –name 容器名称
    -d 后台方式启用
    -it 使用交互方式运行
    -p 指定容器的端口
    -p ip:主机端口:容器端口
    -p 主机端口:容器端口
    -p 容器端口

    docker run -it centos /bin/bash
    docker run -d (后台启动)

注意:容器使用后台运行必须要有前台应用,如果没有前台进程会自动停止,比如启动一个centos 镜像,如果centos 内部没有线程在工作会自动停止

  • 退出

      exit(退出容器中)
    
      ctrl+p+q 容器不停止退出
    
  • docker ps 当前正在运行的容器

      docker ps -a (显示历史的运行的)
    
  • 删除容器

    docker rm 容器id 删除容器
    docker rm -f $(docker ps -aq) 删除所有的
    docker ps -a -q | xargs docker rm 删除所有的容器

  • docker start (id) 启动

  • docker restart (id) 重启

  • docker stop (id) 停止

  • docker kill (id) 杀死

  • 日志

    docker logs -f -t aa8febd62123
    -f 实时追踪
    -t 显示时间戳
    示例: docker logs -f -t –tail 2 aa8febd62123

  • docker top 显示容器内运行的进程信息

     docker top aa8febd62123
    
  • docker insepct ip (显示容器的详细信息,镜像的元数据)

      docker inspect  aa8febd62123 
    
  • docker stats 查看docker 容器的资源消耗情况

  • 进入容器内部

    docker exec -it aa8febd62123 /bin/bash 进入容器后开启一个新的终端,比较常用

    docker attach aa8febd62123 (进入容器正在执行的终端,已经开启了一个终端)

  • 容器拷贝 用于容器与主机之间的数据拷贝

    docker cp aa8febd62123:/test.file /home 将docker容器内的test.file 数据拷贝到主机 /home 里

docker 命令图

docker 部署示例

tomcat

1
docker run  -it --rm -p 5001:8080 tomcat

–rm 是用完即删模式

es

1
2
docker run -d -p 9200:9200  -p9300:9300 -name es  -e "discovery.type=single-node"  -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2  (增加限制内存的操作)

-e 用来传递环境变量

mysql集群

  1. master服务器
1
2
3
4
5
6
7
8
9

docker run -p 3307:3306 --privileged=true --name mysql-master \
-v /data/mysql-master/log:/var/log/mysql \
-v /data/mysql-master/data:/var/lib/mysql \
-v /data/mysql-master/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=111111 \
-d mysql:5.7


–privileged=true 使容器内部root拥有真正的root权限

  1. 新建文件
1
2
vim /data/mysql-master/conf/my.cnf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[mysqld]
## 设置server_id,同一局域网中需要唯一
server_id=101
## 指定不需要同步的数据库名称
binlog-ignore-db=mysql
## 开启二进制日志功能
log-bin=mall-mysql-bin
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed
## 二进制日志过期清理时间。默认值为0,表示不自动清理。
expire_logs_days=7
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062

配置完后重启

1
docker restart mysql-master
  1. 配置用户和授权

    进入mysql-master 中

    1
    docker exec -it dbdcf2ff99ca /bin/bash
    1
    2
    3
    4
    5
    6
    7
    8
    9
    执行登录
    > mysql -u root -p

    //创建用户
    CREATE USER 'slave_user'@'%' IDENTIFIED BY '111111';
    //赋予数据权限
    GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave_user'@'%';
    //刷新权限
    FLUSH PRIVILEGES;
  2. 启动从库

    1
    2
    3
    4
    5
    6
    docker run -p 3308:3306 --name=mysql-slave --privileged=true \
    -v /data/mysql-slave/log:/var/log/mysql \
    -v /data/mysql-slave/data:/var/lib/mysql \
    -v /data/mysql-slave/conf:/etc/mysql \
    -e MYSQL_ROOT_PASSWORD=111111 \
    -d mysql:5.7
  3. 新建从库的配置文件

    1
    vim /data/mysql-slave/conf/my.cnf
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    [mysqld]
    ## 设置server_id,同一局域网中需要唯一
    server_id=102
    ## 指定不需要同步的数据库名称
    binlog-ignore-db=mysql
    ## 开启二进制日志功能,以备Slave作为其它数据库实例的Master时使用
    log-bin=mall-mysql-slave1-bin
    ## 设置二进制日志使用内存大小(事务)
    binlog_cache_size=1M
    ## 设置使用的二进制日志格式(mixed,statement,row)
    binlog_format=mixed
    ## 二进制日志过期清理时间。默认值为0,表示不自动清理。
    expire_logs_days=7
    ## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
    ## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
    slave_skip_errors=1062
    ## relay_log配置中继日志
    relay_log=mall-mysql-relay-bin
    ## log_slave_updates表示slave将复制事件写进自己的二进制日志
    log_slave_updates=1
    ## slave设置为只读(具有super权限的用户除外)
    read_only=1
  4. 重启从数据库

    1
    docker restart mysql-slave
  5. 查看主库的状态

    1
    > show master status;

  6. 拿到主库的同步信息后,到从库设置主从同步

    登录从库 执行主动同步命令

    1
    change master to master_host='192.168.199.101', master_user='slave_user', master_password='111111', master_port=3307, master_log_file='mall-mysql-bin.000001', master_log_pos=779, master_connect_retry=30;  

    参数说明:

    • master_host 主库host
    • master_user 主库配的用于同步的账号
    • master_password 主库配的用于同步的账号密码
    • master_port 主库端口
    • master_log_file 主库日志文件
    • master_log_pos 日志文件的位置
    • master_connect_retry 连接重试间隔 秒
  7. 如果出现错误

    ERROR 1794 (HY000): Slave is not configured or failed to initialize properly. You must at least set –server-id to enable either a master or a slave. Additional error messages can be found in the MySQL error log.

    原因:从 5.6.25 版本使用 innobackupex 备份,在 5.7.15 版本中应用恢复,在 5.6.25 版本中,主从信息记录到了文件中,5.7.15 版本中的主从信息记录的是在表中,所以数据备份后需要对下面几张表进行重建。

    登录主库 操作

    1
    2
    3
    4
    5
    6
    use mysql
    drop table slave_master_info;
    drop table slave_relay_log_info;
    drop table slave_worker_info;
    drop table innodb_index_stats;
    drop table innodb_table_stats;

    找到sql从新导入

    1
    2
    3
    find / -name mysql_system_tables.sql
    source /usr/share/mysql/mysql_system_tables.sql

    docker restart xxx

    重新查看主库的文件和位置;

    修改命令参数,再次连接

    1
    change master to master_host='192.168.199.101', master_user='slave_user', master_password='111111', master_port=3307, master_log_file='mall-mysql-bin.000003', master_log_pos=154, master_connect_retry=30; 

    成功

10 . 查看从库状态

1
> show slave status;
1
2
启动同步
> start slave

  1. 测试向主库中创建数据,可以从从库中查询到;

容器数据卷

每个docker容器中的数据都是相互独立,当容器销毁后数据就被删除,为了使容器中的数据比如数据库的文件数据不因为容器的删除或升级等原因丢失,引用容器的数据卷技术,其实就是将磁盘外部的目录挂载到容器内部.

docker volume ls 查看所有的数据卷

使用命令挂载

docker run -it  -v 主机目录:容器目录
docker inspect id 查看挂载信息
docker run -it -p 4002:8080  -v /home/test:/test  508e138f7dd5 将主机的/home/test 映射为容器内的/test 目录

挂载方式

- 匿名挂载(不指定外部路径) 
    -v 容器内路径
    匿名挂载也有一个默认的容器外的路径,可以通过inspect 查看
-  具名挂载 (起一个可以识别的名字) 

    -v  卷名:容器内路径

- 指定路径挂载

    -v /path:容器内路径

- 权限控制

    -v 卷名:容器内路径:ro (read only 只能读取)
    -v 卷名:容器路径:rw   (可读可写)

数据卷容器

一般用于两个容器之间实现数据共享,就是一个正常的容器,专门用来提供数据卷供其它容器挂载的。

基本命令: -volumes-from 指定从那个数据卷中同步,相当于将父容器的volume 的引用继承过来;

被引用的称为父容器卷,引用的是子容器卷。父容器中的卷中增加或删除内容,子容器卷同步变化;
父容器销毁后,子容器中的内存依然存在;
通过inspect 命令查看,挂载的目录一模一样,所以可以看做是子继承了父的挂载的目录或配置

docker网络

docker 的网络分为单个host的网络或多个host网络

命令 docker network ls 查看所有网络

docker0 网络

安装完docker后,使用 ip addr 命令查看网络 会发现一个docker0的网络,这个网卡是用来桥接所有未指定网络的容器使用的

每启动一个docker容器,docker就给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0 的桥接的模式,使用的技术是evth-pair 技术;
通过容器创建的网卡,都是成对出现的;通过外部和内部的对应进行网络连通;

所有的容器不指定网络的情况下,都是docker0路由的,docker会给容器分配一个默认可用IP;

并且容器和容器之间是可以互相ping通的;

容器之前通过docker0 进行连通;

内置网络

docker 内置三种网络,创建容器的时候可以指定 指定none网络

  • none ( –network=none)用的少,即没有网络需求的容器使用

  • host ( –network=host )网络 ,容器的网络配置与host 一样,容器中可以看到host的网卡信息
    直接占用主机的端口信息,同时端口映射-p 失效 docker run -it –rm –network=host -p 5001:8080 tomcat 需要访问的是8080端口,
    主机8080端口被占用;

  • bridge (–network=bridge )默认,也就是使用docker0 网卡进行桥接的模式

  • container (–network=container) 用于连接一个容器和另一个容器,容器内互通(用的比较少,连接的容器间可以用localhost 访问)

    基本使用 docker run -d –name nginx –net container:xx nginx (xx 是另一个容器名称)

自定义网络

docker 支持创建用户自定义的网络,其中网络驱动可以选择 bridge , overlay 其中 bridge 仅仅支持单机网络

  • docker network ls 列出所有网络

  • docker network create [OPTIONS] NETWORK 创建网络

docker network create -d bridge my-bridge-network 创建一个默认的bridge单机网络

  • docker network connect [OPTIONS] NETWORK CONTAINER 容器加入网络

    加入同一个网络的容器可以通过容器名称进行ping 通
    docker network connect –alias db –alias mysql multi-host-network container2

  • docker network disconnect 停止连接网络

    docker network disconnect [OPTIONS] NETWORK CONTAINER

  • docker network inspect 查看网络信息

  • docker network rm 删除指定网络

  • docker network prune 删除所有未使用的网络

示例:

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
53
54
55
56
57
58
59
60
启动2个容器:

docker pull centos:centos7.9.2009

docker run -it --name centos7_1 centos:centos7.9.2009


docker run -it --name centos7_2 centos:centos7.9.2009

分别启动2个名字为 centos7_1 和 centos7_2 的容器;

相互之间使用 名称或容器id 进行ping 是不通的 Name or service not known

创建一个网络

docker network create -d bridge centos-network

查看网络

docker network ls

NETWORK ID NAME DRIVER SCOPE
b124b2f59f2c bridge bridge local
7415e15246d8 centos-network bridge local
ea9234805906 host host local
a09b1be74233 my-bridge-network bridge local
204727ef2653 my-network bridge local
dbc82c292892 none null local


//2个都加入到网络
docker network connect centos-network 2c9334dee319
docker network connect centos-network 27549423efd0

//查看网络
docker network inspect centos-netwok
可以看到 Containers 中显示了2个容器


"Attachable": false,
"Containers": {
"27549423efd0ca1db4bcc16eb4efc219bed77b6a4e9ade4e1954faaaaa983f49": {
"Name": "centos7_2",
"EndpointID": "499ad45b942a54cfd8c2942b023ecb1ca8ea75e7033f0e12643f45f9881c7c30",
"MacAddress": "02:42:ac:14:00:03",
"IPv4Address": "172.20.0.3/16",
"IPv6Address": ""
},
"2c9334dee3192e025ef78c92fb8eae337e60a27332ac4f37167f62f8966fd849": {
"Name": "centos7_1",
"EndpointID": "690085f03a2c64ac942af918b70f968c1003c665a27377b64fcf2cf8a63110be",
"MacAddress": "02:42:ac:14:00:02",
"IPv4Address": "172.20.0.2/16",
"IPv6Address": ""
}
},

//并且通过ping 容器id 或ping 容器名称可以互相ping通了


docker file

官网文档 https://docs.docker.com/engine/reference/builder/

一个用来构建docker 镜像的文件,就是一个命令的脚本.官方的镜像文件都是基础包,不包含多余的软件,所以我们需要定制适合自己的镜像;

文件格式

  • 关键字必须大写字母

  • # 是注释

  • 执行顺序从上到下执行

  • 每个指令都创建一个镜像层

  • 文件名称可以使用Dockerfile

指令说明

  • FROM
    指定基础镜像,从哪个镜像开始构建

  • MAINTAINER
    作者,镜像是谁写的,姓名+邮箱

  • RUN
    镜像构建的时候需要运行的命令

  • ADD
    复制文件会自动解压

  • WORKDIR
    镜像工作目录

  • VOLUME
    挂载的目录,定义匿名的数据卷

  • EXPOSE
    暴露的端口配置

    EXPOSE 80/tcp
    EXPOSE 80/udp

  • CMD
    容器启动的时候要指定的命令,只有最后一个CMD 会生效

  • ENTRYPOINT
    容器启动的时候的命令,可以追加命令
    CMD 和 ENTRYPOINT 的区别,执行命令的时候,ENTRYPOINT 可以追加命令

  • COPY
    类似ADD将文件拷贝到镜像中

  • ENV
    构建的时候设置环境变量

  • ARG

    构建参数,与 ENV 作用一致。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。

构建命令 docker build 中可以用 –build-arg <参数名>=<值> 来覆盖。

  • USER

    指定执行后续命令的用户或用户组 (用户或用户组 必须已经存在)
    USER <用户名>[:<用户组>]

  • LABEL

    给镜像添加一些元数据,以键值对的方式存在
    LABEL org.opencontainers.image.authors=”xx” 添加镜像作者

创建一个简单的镜像

  1. 编写文件
1
> vim Dockerfile
  1. 写入内容
1
2
3
4
5
6
7
8
FROM centos
MAINTAINER test<test@sina.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim && yum -y install net-tools
EXPOSE 80
CMD bin/bash

每个命令将是一个层,为了减少层,可以使用 && 连接多个命令

  1. 使用dockerbuild 将docker file 构建成镜像
1
2
docker build -f /usr/local/Dockerfile -t hello/centos .

注意:路径用绝对路径 后面还有一个点

docker build 说明

–build-arg 构建过程环境遍历
–tag tag
–file 文件路径

打包一个tomcat镜像

通过基础的centos 镜像中加入自己的jdk和tomcat文件来自定义tomcat镜像

  1. 上传要打包的镜像

  1. 编写Dockerfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
FROM centos
MAINTAINER test<test@sina.com>

ADD jdk-8u291-linux-x64.tar.gz /usr/local
ADD apache-tomcat-9.0.48.tar.gz /usr/local

RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_291
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.48
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.48
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.48/bin/startup.sh && tail -f /usr/local/apache-tomcat-9.0.48/logs/catalina.out

  1. 构建镜像
1
2
docker build -f /usr/local/dockerfiles/mytomcat -t mytomcat:1.0 

  1. 运行镜像
1
2
docker run -d --name mytomcat -p 7001:8080  b280efbfc97f  

其他

虚悬镜像

在docker 镜像的创建的过程中出现的 镜像的仓库 和镜像的标签都是 none的 镜像叫做虚悬镜像。这种镜像是因为错误导致的,在工作中应该避免。

[CMD和ENTRYPOINT的区别]

  1. RUN 执行命令并创建新的镜像层,RUN 经常用于安装软件包,打包时的命令使用RUN
  2. CMD 设置容器启动后默认执行的命令及其参数,但 CMD 能够被 docker run 后面跟的命令行参数替换。
  3. ENTRYPOINT 配置容器启动时运行的命令。

docker参数–restart=always的作用

创建容器时没有添加参数 --restart=always ,导致的后果是:当 Docker 重启时,容器未能自动启动。

Docker容器的重启策略如下:

  • no,默认策略,在容器退出时不重启容器
  • on-failure,在容器非正常退出时(退出状态非0),才会重启容器
  • on-failure:3,在容器非正常退出时重启容器,最多重启3次
  • always,在容器退出时总是重启容器
  • unless-stopped,在容器退出时总是重启容器,但是不考虑在Docker守护进程启动时就已经停止了的容器

为没有设置此配置的容器添加此参数 docker container update –restart=always 容器名字

这样当执行 systemctl restart docker 的时候 ,才能自动启动。