Build Once, Run Anywhere
参考文档
https://blog.stanley.wang
https://gitee.com/stanleywang/projects
容器由来
虚拟化技术
容器技术
docker起源
namespace资源隔离
容器简史
- chroot
- Solaris Continers
- cgroups
- LXC
- Docker
- windows Containers
docker是什么
- docker是基于容器技术的轻量级虚拟化解决方案
- docker是容器引擎,把Linux的cgroup、namespace等容器底层技术进行封装抽象为用户提供创建和管理容器的便捷界面(命令行和API)
- docker是一个开源项目,诞生与2013年,基于google公司的go语言实现
- 微软,Redhat,IBM,Oracle等主流IT厂商已经在自己的产品里增加了对docker的支持
- 相比其它早期的容器技术,docker引入了一整套容器管理的生态系统,包括分层的镜像模型,容器注册库,友好的Rest API
docker优势
docker引擎版本
- 企业版(EE)
- 社区版(CE)
2017年以前 版本号 大版本号.小版本号 最后一个版本 1.13
2018年以后 版本号 YY.MM-XX 第一个社区版 18.06.0-ce
docker引擎安装
centos7安装docker
yum install -y yum-utils device-mapper-persistent-data lvm2 wget
wget -O /etc/yum.repos.d/docker-ce.repo https://download.docker.com/linux/centos/docker-ce.repo
或
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
sed -i 's+download.docker.com+mirrors.tuna.tsinghua.edu.cn/docker-ce+' /etc/yum.repos.d/docker-ce.repo
yum list docker-ce --showduplicates # 查看有哪些版本
yum install docker-ce-x.x.x -y
ubuntu20.4安装docker
apt -y install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | apt-key add -
add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
apt update
apt install docker-ce
rocky9安装docker
dnf install epel-release
dnf install elrepo-release
dnf check-update
dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
dnf install docker-ce
docker引擎配置
cat /etc/docker/daemon.json
{
"graph": "/data/docker",
"storage-driver": "overlay2",
"insecure-registries": ["registry.access.redhat.com","quay.io"],
"registry-mirrors": ["https://q2gr04ke.mirror.aliyuncs.com"],
"bip": "172.7.5.1/24",
"exec-opts": ["native.cgroupdriver=systemd"],
"live-restore": true,
"hosts": ["tcp://0.0.0.0:2375", "unix:///var/run/docker.sock"]
}
附:windows docker引擎配置文件
C:\Users\Administrator\.docker\daemon.json
docker引擎目录
mkdir /data/docker -p
systemd管理dockerd
vim /etc/systemd/system/docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
ExecStart=/usr/bin/dockerd -H tcp://127.0.0.1:2375 -H unix://var/run/docker.sock --graph /webpro/data1/lib/docker
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
注意:/etc/docker/daemon.json 与 docker.service 两个文件不能有相同的配置,否则docker不能启动!!!
docker不能启动可以使用以下命令查看报错信息
journalctl -amu docker
unable to configure the Docker daemon with file /etc/docker/daemon.json: the following directives are specified both as a flag and in the configuration file: graph:
启动docker引擎
systemctl start docker.service
docker引擎信息查看
docker info
Client:
Debug Mode: false
Server:
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 0
Server Version: 19.03.9
Storage Driver: overlay2
Backing Filesystem: xfs
Supports d_type: true
Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: systemd
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 7ad184331fa3e55e52b890ea95e65ba581ae3429
runc version: dc9208a3303feef5b3839f4323d9beb36df0a9dd
init version: fec3683
Security Options:
seccomp
Profile: default
Kernel Version: 3.10.0-957.el7.x86_64
Operating System: CentOS Linux 7 (Core)
OSType: linux
Architecture: x86_64
CPUs: 2
Total Memory: 1.934GiB
Name: bogon
ID: BVD2:V7VH:KKMA:3G5X:FHDE:FNUX:Z2HD:736F:ORJJ:GPIF:UKVM:OYHS
Docker Root Dir: /data/docker
Debug Mode: false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
registry.access.redhat.com
quay.io
127.0.0.0/8
Registry Mirrors:
https://q2gr04ke.mirror.aliyuncs.com/
Live Restore Enabled: true
WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled
启动第一个容器
docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete
Digest: sha256:6a65f928fb91fcfbc963f7aa6d57c8eeb426ad9a20c7ee045538ef34847f44f1
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
普通用户使用docker
由于docker.sock属于docker组,把普通用户加入docker组即可
ll /var/run/docker.sock
srw-rw----. 1 root docker 0 Apr 15 11:45 /var/run/docker.sock
test用户加入docker组
useradd -G docker test
切换到test用户即可使用docker
docker镜像
镜像结构
${registry_name}/${repository_name}/${image_name}:${tag_name}
docker.io/library/alpine:3.10.1
全球最大的docker镜像仓库
https://hub.docker.com/
登陆dockerhub
docker login docker.io
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: wuxingge
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
搜索镜像
docker search alpine
下载镜像
docker pull alpine
docker pull alpine:3.10.3
docker pull docker.io/library/alpine:3.10.1
docker pull node@sha256:e52468e7b23138b2d34f36be341f6cd8b7b47fbf2215cfdec12ed2d6ac0bd25c
查看本地镜像
docker images
docker image ls
镜像打标签
docker tag 965ea09ff2eb docker.io/wuxingge/alpine:v3.10.3
docker tag f70734b6a266 wuxingge/alpine:latest
推送镜像
docker push docker.io/wuxingge/alpine:v3.10.3
docker push wuxingge/alpine:latest
删除镜像
docker rmi docker.io/wuxingge/alpine:latest
docker rmi -f 965ea09ff2eb #强制删除
docker镜像特性
- docker镜像位于bootfs之上
- 每一层镜像的下面一层称为其父镜像
- 第一层镜像为Base Image
- 容器在最顶层
- 其下的所有层都为readonly
- docker将readonly的FS层称作 “image”
docker容器
查看容器列表
docker ps -a
查看一个容器详细信息
docker container inspect 容器名(或ID)
查看容器id
docker inspect 容器名称 |grep "Id"
"Id": "f6834a5e4d035bd3c85842dd35e5e0c68ad6d81af2db9381cbf1653db09196ca",
容器配置
docker容器根目录/containers/容器id/hostconfig.json
#端口映射
"PortBindings":{"80/tcp":[{"HostIp":"","HostPort":"80"}]}
启动容器(运行镜像)
# 交互式
docker run -it wuxingge/alpine:latest /bin/sh
# 非交互式
docker run --rm wuxingge/alpine:latest /bin/echo hello
# 非交互是启动一个后台容器
docker run -d --name myalpine wuxingge/alpine:latest
docker run -d --name myalpine1 wuxingge/alpine:latest /bin/sleep 300
docker run --ulimit nofile=65535:65535 ...
docker进程在宿主机中可以查到
进入容器
docker exec -it 1aae018284c0 /bin/sh
停止容器
docker stop bd989ff80a21
启动容器
docker start bd989ff80a21
重启容器
docker restart bd989ff80a21
删除容器
docker rm myalpine
docker rm -f myalpine1
删除所有已停止容器
for i in `docker ps -a|grep -i exit|awk '{print $1}'`;do docker rm -f $i;done
查看容器资源使用情况
docker stats 容器名称或id
提交镜像
docker commit myalpine1 wuxingge/alpine:v3.10.3_with_1.txt
导出镜像
docker save 4332dd996165 > alpine:v3.10.3_with_1.txt.tar
docker save -o 归档文件 image [image ...]
导入镜像
docker load < alpine\:v3.10.3_with_1.txt.tar
docker load -i 归档文件
查看容器日志
docker run hello-world 2>&1 >>/dev/null
docker logs 容器名称或id
docker logs -f 容器名称或id
docker logs -f -t --since="2018-11-02" --tail=100 容器名称或id
查看容器(或镜像)详细信息
docker inspect nginx_with_web
映射端口
docker run --rm --name mynginx -d -p 81:80 wuxingge/nginx:v1.12.2
挂载数据卷
docker run -d --rm --name nginx_with_web -p 82:80 -v /root/html:/usr/share/nginx/html wuxingge/nginx:v1.12.2
传递环境变量
docker run --rm -e E_OPTS=abcdefg wuxingge/alpine:latest printenv
docker run --rm -e E_OPTS=abcdefg -e C_OPTS=123456 wuxingge/alpine:latest printenv
容器内安装软件
docker exec -it nginx_with_web /bin/bash
tee /etc/apt/sources.list << EOF
deb http://mirrors.163.com/debian/ jessie main non-free contrib
deb http://mirrors.163.com/debian/ jessie-updates main non-free contrib
EOF
apt-get update
apt-get install curl -y
docker commit -p bcbada47af68 wuxingge/nginx:curl
docker push wuxingge/nginx:curl
容器的生命周期
- docker客户端连接docker daemon,请求运行容器
- docker daemon 检查本地是否存在镜像,如果不存在则从远端仓库检索
- 利用镜像启动容器
- 分配一个文件系统,并在只读的镜像层外挂载一层可读写层
- 从宿主机配置的网桥接口中桥接一个虚拟接口到容器
- 从地址池配置一个ip地址给容器
- 执行用户指定的指令
- 执行完毕后容器终止
Dockerfile
docker通过读取Dockerfile中的指令自动构建镜像
docker镜像制作
- docker commit
- Dockerfile
Dockerfile规则
-
格式
- #为注释
- 指令(大写) 内容(小写)
-
docker是按顺序执行Dockerfile里的指令集合的(从上到下依次执行)
-
每一个Dockerfile的第一个非注释行指令,必须是 "FROM"指令,用于指定基准镜像,后续指令运行于此基准镜像所提供的运行环境
Dockerfile指令
- USER
- WORKDIR
vi /data/dockerfile/Dockerfile
FROM wuxingge/nginx:v1.12.2
USER nginx
WORKDIR /usr/share/nginx/html
构建镜像
docker build . -t docker.io/wuxingge/nginx:v1.12.2_with_user_workdir
运行容器测试镜像
docker run --rm -it --name nginx123 wuxingge/nginx:v1.12.2_with_user_workdir /bin/bash
- ADD
- EXPOSE
FROM stanleyws/nginx:v1.12.2
ADD index.html /usr/share/nginx/html/index.html
EXPOSE 80
docker build . -t wuxingge/nginx:v1.12.2_with_add_expose
测试
docker run --rm -d --name nginx123 -P wuxingge/nginx:v1.12.2_with_add_expose
- RUN
- ENV
FROM centos:7
ENV VER 9.11.4-16.P2.el7_8.3
RUN yum install bind-$VER -y
docker build . -t wuxingge/bind:v9.9.4_with_env_run
docker run -it --rm wuxingge/bind:v9.9.4_with_env_run /bin/bash
- CMD
FROM centos:7
RUN yum install httpd -y
CMD ["httpd","-D","FOREGROUND"]
docker build . -t wuxingge/httpd:test
docker run -d --rm --name myhttpd -p 83:80 wuxingge/httpd:test
- ENTRYPOINT
FROM centos:7
ADD entrypoint.sh /entrypoint.sh
RUN yum install epel-release -q -y && yum install nginx -y
ENTRYPOINT /entrypoint.sh
entrypoint.sh
#!/bin/bash
/sbin/nginx -g "daemon off;"
docker build . -t wuxingge/nginx:mynginx
docker run --rm -p 84:80 wuxingge/nginx:mynginx
Dockerfile
FROM wuxingge/nginx:v1.12.2
USER root
ENV WWW /usr/share/nginx/html
ENV CONF /etc/nginx/conf.d
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
echo 'Asia/Shanghai' >/etc/timezone
WORKDIR $WWW
ADD index.html $WWW/index.html
ADD demo.od.com.conf $CONF/demo.od.com.conf
EXPOSE 80
CMD ["nginx","-g","daemon off;"]
vi demo.od.com.conf
server {
listen 80;
server_name demo.od.com;
root /usr/share/nginx/html;
}
docker build . -t wuxingge/nginx:baidu
docker run --rm -P wuxingge/nginx:baidu
docker网络
NAT(默认)
Bridge:Docker设计的NAT网络模型
None
None:不为容器配置任何网络功能
--net=none
Host
Host:与主机共享Network Namespace
--net=host
联合网络
Container:与另一个运行中的容器共享Network Namespace
--net=container:containerID
docker run -it --rm --name lhwl2 --network container:c31d45c54227 wuxingge/nginx:curl /bin/bash
Docker容器化封装应用程序的意义(好处)
-
docker引擎统一了基础设施环境 - docker环境
- 硬件的配置
- 操作系统的版本
- 运行时环境的异构
-
docker引擎统一了程序打包(装箱)方式 - docker镜像
- Java程序
- python程序
- nodejs程序
-
docker引擎统一了程序部署(运行)方式 - docker容器
- java -jar … -> docker run …
- python manage.py runserver … -> docker run …
- npm run dev -> docker run …
docker容器化封装应用程序的缺点(坏处)
- 单机使用,无法有效集群
- 随着容器数量的上升,管理成本攀升
- 没有有效的容灾/自愈机制
- 没有预设编排模板,无法实现快速、大规模容器调度
- 没有统一的配置管理中心工具
- 没有容器生命周期的管理工具
- 没有图形化运维管理工具
基于docker容器引擎的开源容器编排工具
- docker compose 、 docker swarm
- Mesosphere + Marathon
- Kubernetes(K8S)
docker-compose(单机版的容器编排工具)
安装pip
yum install -y python2-pip
pypi源
vim ~/.pip/pip.conf
[global]
index-url = https://mirrors.aliyun.com/pypi/simple/
[install]
trusted-host=mirrors.aliyun.com
安装docker-compose
pip install docker-compose
docker可视化管理工具
docker run -d -p 9000:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v /portainer_data:/data --name portainer portainer/portainer
docker run -d --name docker.ui --restart always -v /var/run/docker.sock:/var/run/docker.sock -p 8010:8999 joinsunsoft/docker.ui:1.0.1
#默认用户名密码
ginghan/123456
docker清理磁盘数据
docker image prune -a
docker container prune
docker volume prune
docker network prune
docker system df
docker system events
docker system info
docker system prune
docker system prune -a
#删除72小时之外所有没有被使用的镜像
docker image prune -a --force --filter "until=72h"
个人存储
mkdir -p /data/nascab
docker run -d \
--name nascab \
--restart always \
-v /data/nascab/mydata:/myData \
-v /data/nascab/data:/root/.local/share/nascab \
-p 8760:80 -p 5620:90 \
ypptec/nascab
附
docker container inspect 容器名称|容器id -f '{{.Name}} {{.HostConfig.NetworkMode}} {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'
docker container inspect `docker ps -aq` -f '{{.Name}} {{.HostConfig.NetworkMode}} {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'
docker network inspect 网络名称|网络id -f '{{.Name}} {{range .IPAM.Config}}{{.Subnet}}{{end}}'
docker network inspect pro-net -f '{{.Name}} {{range .IPAM.Config}}{{.Subnet}}{{end}}'