Docker基础

Docker基础

容器简介

什么是 Linux 容器

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

容器提供的镜像包含了应用的所有依赖项,因而在从开发到测试再到生产的整个过程中,它都具有可移植性和一致性。

图片

在开发应用程序的过程中,开发者通常会面临环境配置不一致的问题。开发者自己的笔记本电脑上的开发环境可能与其他开发人员的环境有所差异,同时还需要考虑到企业的标准化测试和生产环境,这些环境都有自己的配置和必须的支持文件。

为了确保应用程序能够在不同的环境中稳定运行,并通过质量检测,同时在部署过程中避免出现问题,减少重新编写代码和修复故障的需求,可以使用容器技术。容器能够包含应用程序运行所需的所有配置和文件,确保应用程序可以在开发、测试和生产的整个流程中无缝运行,从而避免潜在的危机,实现各方满意的结果。这种方式允许开发者在本地模拟标准化的环境,而不需要承担重建服务器环境的成本和劳力。

容器不就是虚拟化吗

是,但也不竟然。我们用一种简单方式来思考一下:

虚拟化使得许多操作系统可同时在单个系统上运行。

容器则可共享同一个操作系统内核,将应用进程与系统其他部分隔离开。

图片

这意味着什么?首先,让多个操作系统在单个虚拟机监控程序上运行以实现虚拟化,并不能达成和使用容器同等的轻量级效果。

事实上,在仅拥有容量有限的有限资源时,您需要能够可以进行密集部署的轻量级应用。

Linux 容器可从单个操作系统运行,在所有容器中共享该操作系统,因此应用和服务能够保持轻量级,并行快速运行。

什么是 Docker

“Docker” 一词指代多种事物,包括开源社区项目、开源项目使用的工具、主导支持此类项目的公司 Docker Inc. 以及该公司官方支持的工具。技术产品和公司使用同一名称,的确让人有点困惑。

Docker 是一个开源的平台,它使用容器技术来使应用程序的部署、运行和管理变得简单、快速。容器可以被视为轻量级、可移植、自给自足的包,它包含了运行应用程序所需的一切:代码、运行时环境、库、环境变量和配置文件。

借助 Docker ,您可将容器当做重量轻、模块化的虚拟机使用。同时,您还将获得高度的灵活性,从而实现对容器的高效创建、部署及复制,并能将其从一个环境顺利迁移至另一个环境。

Docker 如何工作

Docker 技术使用 Linux 内核和内核功能(例如 Cgroups 和 namespaces)来分隔进程,以便各进程相互独立运行。

这种独立性正是采用容器的目的所在;它可以独立运行多种进程、多个应用程序,更加充分地发挥基础设施的作用,同时保持各个独立系统的安全性。

容器工具(包括 Docker)可提供基于镜像的部署模式。这使得它能够轻松跨多种环境,与其依赖程序共享应用或服务组。Docker 还可在这一容器环境中自动部署应用程序(或者合并多种流程,以构建单个应用程序)。

此外,由于这些工具基于 Linux 容器构建,使得 Docker 既易于使用,又别具一格 —— 它可为用户提供前所未有的高度应用程访问权限、快速部署以及版本控制和分发能力。

docker的目标

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

每一个容器,他都有自己的文件系统rootfs.

Docker基础

Docker基础命令操作

查看docker相关信息

docker version

配置docker镜像加速

vi /etc/docker/daemon.json

修改为以下内容

{
  "registry-mirrors": ["https://registry.docker-cn.com"]
}

启动第一个容器

docker run -d -p 80:80 nginx

参数说明

图片

Docker镜像生命周期

图片

Docker镜像相关操作

搜索官方仓库镜像

docker search centos

列表说明

图片

获取镜像

根据镜像名称拉取镜像

docker pull centos

查看当前主机镜像列表

docker image list

拉第三方镜像方法

docker pull index.tenxcloud.com/tenxcloud/httpd

导出镜像

docker image list 
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              latest              ff426288ea90        3 weeks ago         207MB
nginx               latest              3f8a4339aadd        5 weeks ago         108MB
# 导出
docker image save centos > docker-centos.tar.gz

删除镜像

docker image rm centos:latest

导入镜像

docker image load -i docker-centos.tar.gz

查看镜像的详细信息

docker image inspect centos

容器的日常管理

容器的起/停

最简单的运行一个容器

docker run nginx

创建容器,两步走(不常用)

docker create centos:latest  /bin/bash
docker start stupefied_nobel

快速启动容器方法

docker run  centos:latest  /usr/bin/sleep 20;

容器内的第一个进程必须一直处于运行的状态,否则这个容器,就会处于退出状态!

查看正在运行的容器

docker container ls
# 或
docker ps

查看你容器详细信息/ip

docker container  inspect  容器名称/id

查看你所有容器(包括未运行的)

docker ps -a

停止容器

docker stop 容器名称/id 
# 或
docker container  kill  容器名称/id

进入容器方法

启动时进去方法

docker run -it
#参数:-it 可交互终端
docker run -it nginx:latest  /bin/bash

退出/离开容器

ctrl+p
# 或
ctrl+q

启动后进入容器的方法

attach进入容器,使用pts/0 ,会让所用通过此方法进如放入用户看到同样的操作。

docker attach 容器名称/id

exec 进入容器方法(推荐使用),会重新分配一个终端。

docker exec -it clsn1  /bin/bash

删除所有容器

docker rm -f  `docker ps -a -q`
# -f 强制删除

启动时进行端口映射

-p参数端口映射

docker run -d -p 8888:80  nginx:latest

不同指定映射方法

图片

随机映射 -P 需要镜像支持

Docker 数据卷的管理

挂载时创建卷

挂载卷

docker run -d -p 80:80 -v /data:/usr/share/nginx/html nginx:latest

容器内站点目录: /usr/share/nginx/html

在宿主机写入数据,查看

echo "<h1>test</h1>" >/data/index.html
curl 10.0.0.100:8080

设置共享卷,使用同一个卷启动一个新的容器

docker run -d -p 8080:80 -v /data:/usr/share/nginx/html nginx:latest
curl 10.0.0.100:8080

查看卷列表

docker volume ls

创建卷后挂载

创建一个卷

docker volume create

查看卷路径

docker volume inspect clsn

使用卷启动容器

docker run -d -p 9000:80 -v clsn:/usr/share/nginx/html nginx:latest
# 宿主机测试
echo '<h1>test</h1>' >/var/lib/docker/volumes/clsn/_data/index.html
curl 10.0.0.100:9000blog.nmtui.com

设置卷启动容器

docker run  -d  -P  --volumes-from 券ID nginx:latest 

手动将容器保存为镜像

本次是基于docker官方centos 6.8 镜像创建

启动一个centos6.8的镜像

docker pull  centos:6.8
docker run -it -p 1022:22 centos:6.8  /bin/bash
# 在容器种安装sshd服务,并修改系统密码
/ # yum install  openssh-server -y
/ # echo "root:123456" |chpasswd
/ # /etc/init.d/sshd start

启动完成后镜像ssh连接测试

将容器提交为镜像

docker commit brave_mcclintock  centos6-ssh

使用新的镜像启动容器

docker run -d  -p 1122:22  centos6-ssh:latest  /usr/sbin/sshd -D 

在容器安装httpd服务

# yum install httpd -y

编写启动脚本脚本

# cat init.sh
#!/bin/bash 
/etc/init.d/httpd start 
/usr/sbin/sshd -D
# chmod +x init.sh 
# 注意执行权限

再次提交为新的镜像

docker commit  容器ID centos6-httpd

启动镜像,做好端口映射

docker run -d -p 1222:22 -p 80:80  centos6-httpd /init.sh

Dockerfile自动构建docker镜像

官方构建dockerffile文件参考

https://github.com/CentOS/CentOS-Dockerfiles

Dockerfile指令集

dockerfile主要组成部分:

dockerfile常用指令:

dockerfile其他指令:

创建一个Dockerfile

创建第一个Dockerfile文件

# 创建目录
mkdir /op/base
cd /opt/base
# 创建Dcokerfile文件,注意大小写
vim Dockerfile
# 内容如下
FROM centos:6.8
RUN yum install openssh-server -y 
RUN echo "root:123456" |chpasswd
RUN /etc/init.d/sshd start 
CMD ["/usr/sbin/sshd","-D"]

构建docker镜像

docker image build  -t centos6.8-ssh . 
# -t 为镜像标签打标签  . 表示当前路径

使用自构建的镜像启动

docker run -d -p 2022:22 centos6.8-ssh-b

Docker中的镜像分层

参考文档:

http://www.maiziedu.com/wiki/cloud/dockerimage/

Docker 支持通过扩展现有镜像,创建新的镜像。实际上,Docker Hub 中 99% 的镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的。

图片

从上图可以看到,新镜像是从 base 镜像一层一层叠加生成的。每安装一个软件,就在现有镜像的基础上增加一层。

Docker 镜像为什么分层

镜像分层最大的一个好处就是共享资源。

比如说有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像;同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。

如果多个容器共享一份基础镜像,当某个容器修改了基础镜像的内容,比如 /etc 下的文件,这时其他容器的 /etc 是不会被修改的,修改只会被限制在单个容器内。这就是容器 Copy-on-Write 特性。

可写的容器层

当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。

图片

所有对容器的改动 - 无论添加、删除、还是修改文件都只会发生在容器层中。只有容器层是可写的,容器层下面的所有镜像层都是只读的。

容器层的细节说明

镜像层数量可能会很多,所有镜像层会联合在一起组成一个统一的文件系统。如果不同层中有一个相同路径的文件,比如 /a,上层的 /a 会覆盖下层的 /a,也就是说用户只能访问到上层中的文件 /a。在容器层中,用户看到的是一个叠加之后的文件系统。

文件操作的

图片

只有当需要修改时才复制一份数据,这种特性被称作 Copy-on-Write。可见,容器层保存的是镜像变化的部分,不会对镜像本身进行任何修改。

这样就解释了我们前面提出的问题:容器层记录对镜像的修改,所有镜像层都是只读的,不会被容器修改,所以镜像可以被多个容器共享。

使用docker运行zabbix-server

容器间的互联

在运行zabbix之前务必要了解容器间互联的方法

# 创建一个nginx容器
docker run -d -p 80:80 nginx
# 创建容器,做link,并进入容器中
docker run -it --link quirky_brown:web01 centos-ssh /bin/bash
# 在容器中访问nginx容器可以ping通
ping web01

命令执行过程

# 启动apache容器
docker run -d httpd:2.4 
docker ps -a

# 拉取一个busybox 镜像
docker pull busybox 
# 启动容器
docker run -it  --link determined_clarke:web busybox:latest   /bin/sh
# 使用新的容器访问最初的web容器
/ # ping web      

启动zabbix容器

1、启动一个mysql的容器

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_bin

2、启动java-gateway容器监控java服务

docker run --name zabbix-java-gateway -t \
      -d zabbix/zabbix-java-gateway:latest

3、启动zabbix-mysql容器使用link连接mysql与java-gateway。

docker 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:latest

4、启动zabbix web显示,使用link连接zabbix-mysql与mysql。

docker 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

关于zabbix API

关于zabbix API可以参考官方文档:

https://www.zabbix.com/documentation/3.4/zh/manual/api

1、获取token方法

# 获取token
curl -s -X POST -H 'Content-Type:application/json' -d '
{
"jsonrpc": "2.0",
"method": "user.login",
"params": {
"user": "Admin",
"password": "zabbix"
},
"id": 1
}' http://10.0.0.100/api_jsonrpc.php
{"jsonrpc":"2.0","result":"d3be707f9e866ec5d0d1c242292cbebd","id":1}

docker 仓库(registry)

创建一个普通仓库

1、创建仓库

docker run -d -p 5000:5000 --restart=always --name registry -v /opt/myregistry:/var/lib/registry  registry 

2、修改配置文件,使之支持http

cat  /etc/docker/daemon.json 
{
  "registry-mirrors": ["https://registry.docker-cn.com"],
  "insecure-registries": ["10.0.0.100:5000"]
}
# 重启docker让修改生效
systemctl restart  docker.service

3、修改镜像标签

docker tag  busybox:latest  10.0.0.100:5000/clsn/busybox:1.0
docker images

4、将新打标签的镜像上传镜像到仓库

docker push 10.0.0.100:5000/clsn/busybox

带basic认证的仓库

1、安装加密工具

yum install httpd-tools  -y

2、设置认证密码

mkdir /opt/registry-var/auth/ -phtpasswd  -Bbn clsn 123456  > /opt/registry-var/auth/htpasswd

3、启动容器,在启动时传入认证参数

docker run -d -p 5000:5000 -v /opt/registry-var/auth/:/auth/ -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd registry

4、使用验证用户测试

# 登陆用户
docker login 10.0.0.100:5000 
# 推送镜像到仓库
docker push 10.0.0.100:5000/clsn/busybox 
#认证文件的保存位置
cat .docker/config.json 
{
    "auths": {
        "10.0.0.100:5000": {
            "auth": "Y2xzbjoxMjM0NTY="
        },
        "https://index.docker.io/v1/": {
            "auth": "Y2xzbjpIenNAMTk5Ng=="
        }
    },
    "HttpHeaders": {
        "User-Agent": "Docker-Client/17.12.0-ce (linux)"
    }
}

docker-compose编排工具

安装docker-compose

安装docker-compose

# 下载pip软件
yum install -y python2-pip
# 下载 docker-compose
pip install docker-compose

国内开启pip 下载加速:

http://mirrors.aliyun.com/help/pypi

mkdir ~/.pip/
cat > ~/.pip/pip.conf <<'EOF'
[global]
index-url = https://mirrors.aliyun.com/pypi/simple/
[install]
trusted-host=mirrors.aliyun.com
EOF

编排启动镜像

1、创建文件目录

mkdir /opt/my_wordpress/
cd /opt/my_wordpress/

2、编写编排文件

编排文件 docker-compose.yml 内容如下

version: '3'
services:
   db:
     image: mysql:5.7
     volumes:
       - /data/db_data:/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
     volumes:
       - /data/web_data:/var/www/html
     ports: 
       - "8000:80"
     restart: always
     environment:
       WORDPRESS_DB_HOST: db:3306
       WORDPRESS_DB_USER: wordpress
       WORDPRESS_DB_PASSWORD: wordpress

3、启动

docker-compose up

4、浏览器上访问 http://10.0.0.100:8000

进行wordpress的安装即可

Docker网络类型

图片

图片

Bridge默认docker网络隔离基于网络命名空间,在物理机上创建docker容器时会为每一个docker容器分配网络命名空间,并且把容器IP桥接到物理机的虚拟网桥上。

不为容器配置网络功能

此模式下创建容器是不会为容器配置任何网络参数的,如:容器网卡、IP、通信路由等,全部需要自己去配置。

docker run  -it --network none busybox:latest  /bin/sh 
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever

与其他容器共享网络配置(Container)

此模式和host模式很类似,只是此模式创建容器共享的是其他容器的IP和端口而不是物理机,此模式容器自身是不会配置网络和端口,创建此模式容器进去后,你会发现里边的IP是你所指定的那个容器IP并且端口也是共享的,而且其它还是互相隔离的,如进程等。

docker run  -it --network container:mywordpress_db_1  busybox:latest  /bin/sh 
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
105: eth0@if106: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:12:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.3/16 brd 172.18.255.255 scope global eth0
       valid_lft forever preferred_lft forever

使用宿主机网络

此模式创建的容器没有自己独立的网络命名空间,是和物理机共享一个Network Namespace,并且共享物理机的所有端口与IP,并且这个模式认为是不安全的。

docker run  -it --network host  busybox:latest  /bin/sh

查看网络列表

docker network list

用PIPEWORK为docker容器配置独立IP

1、安装pipework

wget https://github.com/jpetazzo/pipework/archive/master.zipunzip master.zip cp pipework-master/pipework  /usr/local/bin/chmod +x /usr/local/bin/pipework

2、配置桥接网卡

安装桥接工具

yum install bridge-utils.x86_64 -y

修改网卡配置,实现桥接

# 修改eth0配置,让br0实现桥接
cat /etc/sysconfig/network-scripts/ifcfg-eth0 
TYPE=Ethernet
BOOTPROTO=static
NAME=eth0
DEVICE=eth0
ONBOOT=yes
BRIDGE=br0

cat /etc/sysconfig/network-scripts/ifcfg-br0 
TYPE=Bridge
BOOTPROTO=static
NAME=br0
DEVICE=br0
ONBOOT=yes
IPADDR=10.0.0.100
NETMASK=255.255.255.0
GATEWAY=10.0.0.254
DNS1=223.5.5.5

# 重启网络
/etc/init.d/network restart

3、运行一个容器镜像测试:

pipework br0 $(docker run -d -it -p 6880:80 --name  httpd_pw httpd) 10.0.0.220/24@10.0.0.254

在其他主机上测试端口及连通性

curl 10.0.0.220
ping 10.0.0.220 -c 1

4、再运行一个容器,设置网路类型为none:

pipework br0 $(docker run -d -it --net=none --name test httpd:2.4) 10.0.0.221/24@10.0.0.254

进行访问测试

curl 10.0.0.221

5、重启容器后需要再次指定:

pipework br0 testduliip  172.16.146.113/24@172.16.146.1pipework br0 testduliip01  172.16.146.112/24@172.16.146.1

Docker跨主机通信之macvlan

创建网络

docker network  create --driver macvlan  --subnet 10.1.0.0/24 --gateway 10.1.0.254 -o parent=eth0  macvlan_1

设置网卡为混杂模式

ip link set eth0 promisc on

创建使用macvlan网络容器

docker run  -it --network macvlan_1  --ip=10.1.0.222 busybox /b

使用容器的建议

1. 不要以拆分方式进行应用程序发布

2. 不要创建大型镜像

3. 不要在单个容器中运行多个进程

4. 不要再镜像内保存凭证,不要依赖IP地址

5. 以非root用户运行进程

6. 不要使用“最新”标签

7. 不要利用运行中的容器创建镜像

8. 不要使用单层镜像

9. 不要将数据存放在容器内

参考文献