Docker 容器
一、 什么是容器?(container)

Linux容器是与系统其他部分隔离开的一系列进程,从另一个系统镜像(文件系统)运行,并由该镜像提供支持进程所需的全部文件(环境文件)。

容器镜像包含了应用的所有依赖项,因而在从开发到测试再到生产的整个过程中,它都具有可移植性和一致性。
来源:https://www.redhat.com/zh/topics/containers/whats-a-linux-container

虚拟化使得许多操作系统可同时在单个系统上运行。
容器只能共享操作系统内核,将应用进程与系统其他部分,隔离开。

二、容器和虚拟化的区别
linux容器技术,容器虚拟化和kvm虚拟化的区别
kvm虚拟化: 需要硬件的支持,需要模拟硬件,可以运行不同的操作系统,启动时间分钟级(开机启动流程)
容器虚拟化:不需要硬件的支持。不需要模拟硬件,共用宿主机的内核,启动时间秒级(没有开机启动流程)

总结:
(1)与宿主机使用同一个内核,性能损耗小;
(2)不需要指令级模拟;
(3)容器可以在CPU核心的本地运行指令,不需要任何专门的解释机制;
(4)避免了准虚拟化和系统调用替换中的复杂性;
(5)轻量级隔离,在隔离的同时还提供共享机制,以实现容器与宿主机的资源共享。

三、容器技术的发展过程:
 3.1):chroot技术,新建一个子系统
           参考资料:https://www.ibm.com/developerworks/cn/linux/l-cn-chroot/

 3.2):linux容器(lxc)  linux container(namespaces 隔离环境 及cgroups 硬件资源限制)

 

四、需要使用epel源
  4.1 、安装epel源
           yum install epel-release -y

 4.2、编译epel源配置文件

vi  /etc/yum.repos.d/epel.repo
 [epel]
 name=Extra Packages for Enterprise Linux 7 - $basearch
 baseurl=https://mirrors.tuna.tsinghua.edu.cn/epel/7/$basearch
 #mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-7&arch=$basearch
 failovermethod=priority
 enabled=1
 gpgcheck=1
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7[epel-debuginfo]
 name=Extra Packages for Enterprise Linux 7 - $basearch - Debug
 baseurl=https://mirrors.tuna.tsinghua.edu.cn/epel/7/$basearch/debug
 #mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-debug-7&arch=$basearch
 failovermethod=priority
 enabled=0
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
 gpgcheck=1[epel-source]
 name=Extra Packages for Enterprise Linux 7 - $basearch - Source
 baseurl=https://mirrors.tuna.tsinghua.edu.cn/epel/7/SRPMS
 #mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-source-7&arch=$basearch
 failovermethod=priority
 enabled=0
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
 gpgcheck=1

 

4.3 、安装 lxc

yum install lxc-* -y
 yum install libcgroup* -y
 yum install bridge-utils.x86_64 -y

 4.4 、桥接网卡

[root@controller ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0 
 TYPE=Ethernet
 BOOTPROTO=none
 NAME=eth0
 DEVICE=eth0
 ONBOOT=yes
 BRIDGE=br0 [root@controller ~]# cat /etc/sysconfig/network-scripts/ifcfg-br0 
 TYPE=Bridge
 BOOTPROTO=static
 NAME=br0
 DEVICE=br0
 ONBOOT=yes
 IPADDR=10.0.0.11
 NETMASK=255.255.255.0
 GATEWAY=10.0.0.254
 DNS1=223.5.5.5

 4.5 、修改lxc默认配置
     

vi /etc/lxc/default.conf
         修改第2行为:lxc.network.link = br0

 4.6、启动cgroup
     

systemctl start cgconfig.service

 4.7、启动lxc
   

systemctl start lxc.service

 4.8 、创建 lxc容器

方法1:
 lxc-create -t download -n centos6 -- --server mirrors.tuna.tsinghua.edu.cn/lxc-images -d centos -r 6 -a amd64
 方法2:
 lxc-create -t centos -n test

 

4.9 、为lxc容器设置root密码:

[root@controller ~]# chroot /var/lib/lxc/centos6/rootfs passwd
 Changing password for user root.
 New password: 
 BAD PASSWORD: it is too simplistic/systematic
 BAD PASSWORD: is too simple
 Retype new password: 
 passwd: all authentication tokens updated successfully.

4.10 、为容器指定ip和网关

vi /var/lib/lxc/centos7/config
 lxc.network.name = eth0
 lxc.network.ipv4 = 10.0.0.111/24
 lxc.network.ipv4.gateway = 10.0.0.254

4.11 、启动容器

lxc-start -n centos7

五 、docker容器
Docker是通过内核虚拟化技术(namespaces及cgroups cpu、内存、磁盘io等)来提供容器的资源隔离与安全保障等。由于Docker通过操作系统层的虚拟化实现隔离,所以Docker容器在运行时,不需要类似虚拟机(VM)额外的操作系统开销,提高资源利用率。

namespace(资源隔离)
cgroup(硬件资源的限制)

docker的主要目标是"Build,Ship and Run any App,Angwhere",构建,运输,处处运行

构建:做一个docker镜像
运输:docker pull
运行:启动一个容器
每一个容器,他都有自己的根文件系统rootfs.

kvm解决了硬件和操作系统之间的依赖

docker 解决了软件和操作系统运行环境之间的依赖,能够让独立服务或应用程序在不同的环境中,得到相同的运行结果。

docker容器是一种轻量级、可移植、自包含的软件打包技术,使应用程序可以在几乎任何地方以相同的方式运行。

开发人员在自己笔记本上创建并测试好的容器,无需任何修改就能够在生产系统的虚拟机、物理服务器或公有云主机上运行。

 5.1、docker的安装

wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.ustc.edu.cn/docker-ce/linux/centos/docker-ce.repo
  sed -i 's#download.docker.com#mirrors.ustc.edu.cn/docker-ce#g' /etc/yum.repos.d/docker-ce.repo
  yum install docker-ce -y

 

5.2 、docker的主要组成部分
docker是传统的 CS架构分为 docker client和 docker server,像mysql一样

命令:docker version
[root@controller ~]# docker version 
Client:
 Version:    17.12.0-ce
 API version:    1.35
 Go version:    go1.9.2
 Git commit:    c97c6d6
 Built:    Wed Dec 27 20:10:14 2017
 OS/Arch:    linux/amd64

Server:
 Engine:
  Version:    17.12.0-ce
  API version:    1.35 (minimum version 1.12)
  Go version:    go1.9.2
  Git commit:    c97c6d6
  Built:    Wed Dec 27 20:12:46 2017
  OS/Arch:    linux/amd64
  Experimental:    false
  
docker info(如果要做监控)

###设置docker远程执行
 systemd详解:http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-part-two.html####在linux-node1:
 vim /usr/lib/systemd/system/docker.service
 ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://10.0.0.11:2375
 systemctl daemon-reload
 systemctl restart docker.service
 ps -ef检查####在linux-node2:
 wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.ustc.edu.cn/docker-ce/linux/centos/docker-ce.reposed -i 's#download.docker.com#mirrors.ustc.edu.cn/docker-ce#g' /etc/yum.repos.d/docker-ce.repo
yum install docker-ce -y
docker -H 10.0.0.11 info

docker 主要组件有:镜像、容器、仓库

启动容器必须需要一个镜像,仓库用来存储docker镜像

六 、启动第一个容器

安装Nginx步骤:
官网下载Nginx源码包
创建Nginx用户
编译安装
修改配置文件,
启动

docker run -d -p 80:80 nginx

## 配置docker镜像加速
vi /etc/docker/daemon.json
{
  "registry-mirrors": ["https://registry.docker-cn.com"]
}    

docker run -d -p 80:80 nginx
run(创建并运行一个容器)
-d 放在后台
-p 端口映射
nginx docker镜像的名字(如果找不到Nginx的镜像,就会从docker hub上下载)

七 、docker的镜像管理
搜索镜像
    docker search
选镜像的建议:
1,优先考虑官方
2,starts数量多

获取镜像
    docker pull(push)
    镜像加速器:阿里云加速器,daocloud加速器,中科大加速器,Docker 中国官方镜像加速:https://registry.docker-cn.com
    
    docker pull centos:6.8(没有指定版本,默认会下载最新版)

##配置docker镜像加速
vi /etc/docker/daemon.json
{
  "registry-mirrors": ["https://registry.docker-cn.com"]
}    
    
 第三方docker镜像仓库,使用方法:
docker pull index.tenxcloud.com/tenxcloud/httpd:latest
    
查看镜像
    docker images
导出镜像
    docker save  例子:docker image save centos > docker-centos7.4.tar.gz
    
删除镜像
    docker rmi  例子:docker image rm centos:latest
导入镜像
    docker load  例子:docker image load -i docker-centos7.4.tar.gz
    
    
八 、docker的容器管理
docker run -d -p 80:80 nginx
run(创建并运行一个容器)
-d 放在后台
-p 端口映射
-v  源地址(宿主机):目标地址(容器)

nginx docker镜像的名字

docker run -it --name centos6 centos:6.8 /bin/sh
-it   分配交互式的终端
--name 指定容器的名字
/bin/sh覆盖容器的初始命令

启动容器
    docker run image_name
    docker run -it image_name CMD
    
    docker run ==== docker create  + docker start

停止容器
    docker stop CONTAINER_ID
杀死容器
    docker kill container_name
查看容器列表
    docker ps
    docker ps –a 

删除容器
    docker rm
批量删除容器
    docker rm -f `docker ps -a -q`
    
进入容器
***    docker exec  (会分配一个新的终端tty)
        docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
        
docker exec -it  容器id或容器名字 /bin/bash
        
    docker attach(使用同一个终端)
        docker attach [OPTIONS] CONTAINER
        
    nsenter(安装yum install -y util-linux)

docker run -d nginx:latest (没有指定初始命令,启动容器会使用镜像默认的命令)
docker run -it nginx:latest /bin/bash (指定了初始命令,启动容器会替换镜像默认的命令)
    
总结:docker容器内的第一个进程必须一直处于前台运行的状态(必须夯住),否则这个容器,就会处于退出状态!

 

九 、docker容器的网络访问  NAT

指定映射(docker 会自动添加一条iptables规则来实现端口映射)

-p hostPort:containerPort
     -p ip:hostPort:containerPort 
     -p ip::containerPort(随机端口)
     -p hostPort:containerPort:udp
     -p 81:80 –p 443:443

随机映射
    docker run -P (随机端口)
    

十 、docker的数据卷管理
 /usr/share/nginx/html

数据卷(文件或目录)
    -v dst(容器的目录)
    -v src(宿主机的目录):dst(容器的目录)
数据卷容器
    --volumes-from  容器名或容器id

 

十一 、手动将容器保存为镜像

 11.1):基于容器制作镜像
  案例1

docker run -it -p 1022:22  centos:6.8  /bin/bash
 yum install openssh-server -y
 /etc/init.d/sshd start
 echo "123456"|passwd --stdin rootdocker commit 1d39b94c89b6 centos-ssh:v1
docker run -d -p 2022:22 centos-ssh:v1 /usr/sbin/sshd -D
docker commit 容器id或者容器的名字   新的镜像名字[:版本号可选]

 案例2

docker run -it -p 1022:22 -p 80:80 centos:6.8 /bin/bash
 yum install httpd
 yum install openssh-server
 /etc/init.d/sshd startvi /init.sh
 #!/bin/bash
 /etc/init.d/httpd start
 /usr/sbin/sshd -Dchmod +x /init.sh

 11.2)将容器提交为镜像
docker commit oldboy centos6-ssh-httpd:v1

 11.3)测试镜像功能是否可用
docker run -d -p 2022:22 -p 81:80 centos-ssh-httpd:v1 /bin/bash /init.sh

十二 、dockerfile自动构建docker镜像
dockerfile主要组成部分:
    基础镜像信息       FROM:centos:6.8
    制作镜像操作指令   RUN yum install openssh-server -y
    容器启动时执行指令 CMD ["/bin/bash"]
dockerfile常用指令:
    FROM  这个镜像的妈妈是谁?(指定基础镜像)
    LABEL 告诉别人,谁负责养它?(指定维护者信息,可以没有)
    RUN  你想让它干啥(在命令前面加上RUN即可)
    ADD  给它点创业资金(复制文件,会自动解压)
    WORKDIR 我是cd,今天刚化了妆(设置当前工作目录)
    VOLUME 给它一个存放行李的地方(设置卷,挂载主机目录)
    EXPOSE 它要打开的门是啥(指定对外的端口)(-P 随机端口)
    CMD 奔跑吧,兄弟!(指定容器启动后的要干的事情)(容易被替换)
    
使用ADD的时候,ADD init.sh /init.sh(init.sh文件必须放在Dockerfile同级目录下!!!) 
    
dockerfile其他指令:    
    COPY 复制文件  (复制文件,不会自动解压)
    ENV  环境变量
    ENTRYPOINT  容器启动后执行的命令(无法被替换,启容器的时候指定的命令,会被当成参数)

 

 

十三 、容器间的互联(--link 是单方向的!!!)

docker run -d -p 80:80 nginx
     docker run -it --link nginx:web01 qstack/centos-ssh /bin/bash
     ping web01     使用docker运行zabbix-server
 docker run --name mysql-server -t \
       -e MYSQL_DATABASE="zabbix" \
       -e MYSQL_USER="zabbix" \
       -e MYSQL_PASSWORD="zabbix_pwd" \
       -e MYSQL_ROOT_PASSWORD="root_pwd" \
       -d mysql:5.7 \
       --character-set-server=utf8 --collation-server=utf8_bindocker run --name zabbix-java-gateway -t \
       -d zabbix/zabbix-java-gateway:latestdocker run --name zabbix-server-mysql -t \
       -e DB_SERVER_HOST="mysql-server" \
       -e MYSQL_DATABASE="zabbix" \
       -e MYSQL_USER="zabbix" \
       -e MYSQL_PASSWORD="zabbix_pwd" \
       -e MYSQL_ROOT_PASSWORD="root_pwd" \
       -e ZBX_JAVAGATEWAY="zabbix-java-gateway" \
       --link mysql-server:mysql \
       --link zabbix-java-gateway:zabbix-java-gateway \
       -p 10051:10051 \
       -d zabbix/zabbix-server-mysql:latestdocker run --name zabbix-web-nginx-mysql -t \
       -e DB_SERVER_HOST="mysql-server" \
       -e MYSQL_DATABASE="zabbix" \
       -e MYSQL_USER="zabbix" \
       -e MYSQL_PASSWORD="zabbix_pwd" \
       -e MYSQL_ROOT_PASSWORD="root_pwd" \
       --link mysql-server:mysql \
       --link zabbix-server-mysql:zabbix-server \
       -p 80:80 \
       -d zabbix/zabbix-web-nginx-mysql:latest

十四 、docker registry

##普通的registry
 docker run -d -p 5000:5000 --restart=always --name registry -v /opt/myregistry:/var/lib/registry  registrydocker push index.tenxcloud.com/google_containers/busybox
 1:10.0.0.11:5000/centos6-sshd:v3(手动给它打tag)
 2:vi /etc/docker/daemon.json
 {
   "registry-mirrors": ["https://registry.docker-cn.com"],
   "insecure-registries": ["10.0.0.11:5000"],
 }
 systemctl restart docker
 3.docker push 10.0.0.11:5000/centos6-sshd:v3 ##http带basic认证的registry
 yum install httpd-tools -y
 mkdir /opt/registry-var/auth/ -p
 htpasswd  -Bbn oldboy 123456  >> /opt/registry-var/auth/htpasswddocker run -d -p 5000:5000 -v /opt/registry-var/auth/:/auth/ -v /opt/myregistry:/var/lib/registry -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" registry

十五 、docker-compose(单机版的容器编排工具)

yum install -y python2-pip(需要epel源)
 pip install docker-compose cd my_wordpress/
 vi docker-compose.yml
 version: '3'services:
    db:
      image: mysql:5.7
      volumes:
        - /oldboy:/var/lib/mysql
      restart: always
      environment:
        MYSQL_ROOT_PASSWORD: somewordpress
        MYSQL_DATABASE: wordpress
        MYSQL_USER: wordpress
        MYSQL_PASSWORD: wordpress   wordpress:
      depends_on:
        - db
      image: wordpress:latest
      ports:
        - "80"
      restart: always
      environment:
        WORDPRESS_DB_HOST: db:3306
        WORDPRESS_DB_USER: wordpress
        WORDPRESS_DB_PASSWORD: wordpress
         #启动
 docker-compose up
 #后台启动
 docker-compose up -d

 

十六 、重启docker服务,容器全部退出的解决办法

方法一:docker run  --restart=always
方法二:"live-restore": true
 docker server配置文件/etc/docker/daemon.json参考
 {
  "registry-mirrors": ["http://b7a9017d.m.daocloud.io"],
  "insecure-registries":["10.0.0.11:5000"],
  "live-restore": true
 }