Docker相关知识总结
Centos7安装Docker
-
卸载旧版本
sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-selinux docker-engine-selinux docker-engine
-
安装依赖包
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
-
添加国内yum源
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
-
安装Docker CE
sudo yum makecache fast
sudo yum install docker-ce
-
启动Docker CE
sudo systemctl enable docker
sudo systemctl start docker
-
镜像加速
cat /etc/docker/daemon.json
{
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn"
]
}
#重启服务
sudo systemctl daemon-reload
sudo systemctl restart docker
#查看是否配置成功
sudo docker info
Docker镜像
-
获取镜像
docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]
-
运行
docker run -it --rm ubuntu:18.04 bash
- -it -i交互式操作 -t 终端
- --rm 退出时将其删除
- ubuntu:18.04 以ubuntu:18.04作为基础启动容器
- bash 启动后执行命令
-
列出镜像
docker image ls
-
镜像体积
docker system df
-
虚悬镜像
docker image prune
-
中间层镜像
docker image ls -a
-
列出部分镜像
docker image ls ubuntu
-
以特定格式显示
#列出所有镜像ID
docker image ls -q
#利用模板语法
docker image ls --format "{{.ID}}: {{.Repository}}"
- 删除本地镜像
docker image rm [选项] <镜像1> [<镜像2> ...]
- 构建镜像(commit 慎用)
#以nginx为基础镜像启动一个名为webserver的容器 映射80端口
docker run --name webserver -d -p 80:80 nginx
#进入容器
docker exec -it webserver bash
echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
#查看具体改动
docker diff webserver
#构建镜像
docker commit --author "Ropon" --message "修改默认页面" webserver nginx:V2
#查看镜像
docker image ls nginx
#查看镜像内历史记录
docker history nginx
#测试新镜像
docker run --name web2 -d -p 81:80 nginx:V2
- 用Dockerfile 定制镜像
Dockerfile是一个文本文件 包含一条条指令(Instruction)每条指令构建一层
mkdir mynginx
cd mynginx
cat Dockerfile
FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
#FROM 指定基础镜像(一个特殊镜像 scratch 空白镜像 复制可执行二进制文件打包成新镜像)
#RUN 执行命令(和写shell脚本一样 每行将构建一层 臃肿 不推荐 并不是在写shell脚本 而是在定义每一层该如何构建)
#构建镜像
docker build -t nginx:V3 .
#测试新镜像
docker run --name web3 -d -p 82:80 nginx:V3
- 镜像构建上下文(Context)
#构建在服务端由Docker引擎完成 构建时将指定路径下内容打包 上传给Docker引擎 然后展开构建
COPY ./package.json /app/
#比如以上语句 构建时不是复制docker build命令所在目录下package.json 也不是复制Dockerfile所在目录下package.json 而是复制上下文目录下package.json
docker build -t nginx:V3 .
. 当前目录也就是指定上下文目录 docker build 命令会将该目录打包上传Docker引擎 帮助构建镜像
#发送上下文的过程
Sending build context to Docker daemon 2.048kB
#基于以上理解 构建时新建一个空目录 同时可通过.dockerignore文件忽略
- docker build 用法
#Git repo 进行构建
docker build https://github.com/ropon/docker-test.git
#tar压缩包构建
docker build https://server/context.tar.gz
#读取Dockerfile 进行构建
docker build - < Dockerfile
cat Dockerfile | docker build -
-
Dockerfile 指令详解
-
COPY 复制文件
COPY [--chown=<user>:<group>] <源路径>... <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]
- 例子
COPY package.json /usr/src/app/
COPY home.txt /mydir/
COPY --chown=555:mygroup files* /mydir/
- 例子
-
ADD 高级复制文件
#复制压缩包会自动解压 ADD test.tar.gz /
- CMD 容器启动命令
CMD <命令>
CMD ["可执行文件", "参数1", "参数2"...]
- 例子
CMD echo $HOME
CMD ["nginx", "-g", "daemon off;"]
- ENTRYPOINT 入口点
#1、场景一 带参数 cat Dockerfile FROM ubuntu:18.04 RUN apt-get update \ && apt-get install -y curl \ && rm -rf /var/lib/apt/lists/* ENTRYPOINT ["curl", "-s", "https://ip.ropon.top"] docker build -t myip . #测试 docker run myip -i docker run myip #2、场景2 预处理 FROM alpine:3.4 ... RUN addgroup -S redis && adduser -S -G redis redis ... ENTRYPOINT ["docker-entrypoint.sh"] EXPOSE 6379 CMD [ "redis-server" ]
-
ENV 设置环境变量
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...
-
例子
ENV NODE_VERSION 7.2.0 RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NOD E_VERSION-linux-x64.tar.xz" && curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS25 6.txt.asc" && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.tx t.asc && grep " node-v$NODE_VERSION-linux-x64.tar.xz\$" SHASUMS256.t xt | sha256sum -c - && tar -xJf "node-v$NODE_VERSION-linux-x64.tar.xz" -C /usr/loc al --strip-components=1 && rm "node-v$NODE_VERSION-linux-x64.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt && ln -s /usr/local/bin/node/usr/local/bin/nodejs
-
ARG 构建参数
ARG <参数名>[=<默认值>]
-
VOLUME 定义匿名卷
VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>
- 例子
#向/data 写入信息不会记录容器存储层 VOLUME /data
- 例子
-
EXPOSE 声明端口
EXPOSE <端口1> [<端口2>...]
-
WORKDIR 指定工作目录
WORKDIR <工作目录路径>
-
USER 指定当前用户
USER <用户名>[:<用户组>]
-
例子
RUN groupadd -r redis && useradd -r -g redis redis USER redis RUN [ "redis-server" ]
- HEALTHCHECK 健康检查
HEALTHCHECK [选项] CMD <命令>
- 例子
FROM ubuntu:18.04 RUN apt-get update && apt-get install -y nginx curl && rm -rf /var/lib/apt/lists/* HEALTHCHECK --interval=5s --timeout=3s CMD curl -fs http://localhost/ || exit 1 CMD ["nginx", "-g", "daemon off;"] #启动容器测试 docker run -d --name web -p 80:80 nginx:V4 #查看健康状态 docker inspect --format '{{json .State.Health}}' web | python -m json.tool
-
ONBUILD 为了定制当前镜像而准备
ONBUILD <其它指令>
-
例子
FROM node:slim RUN mkdir /app WORKDIR /app ONBUILD COPY ./package.json /app ONBUILD RUN [ "npm", "install" ] ONBUILD COPY . /app/ CMD [ "npm", "start" ]
-
-
多阶段构建镜像
FROM scratch
WORKDIR /app
COPY testgo .
ENTRYPOINT ["/app/testgo"]
Docker容器
-
启动容器
docker run
- 新建并启动
#新建一个容器 docker run ubuntu:18.04 /bin/echo "hello world" #新建一个容器启动一个终端 用于交互 docker run -t -i ubuntu:18.04 /bin/bash
- 启动已终止容器
docker container start
- 后台运行
docker run -d
-
终止容器
docker container stop
-
进入容器
使用-d 参数时 容器启动后回进入后台 可使用docker attach 或 docker exec(exit退出时容器不会因此停止)
-
导出和导入容器
- 导出容器
docker export 7691a814370e > ubuntu.tar
- 导入容器
cat ubuntu.tar | docker import - test/ubuntu:v1.0
- 导出容器
-
删除容器
docker container rm 或docker rm 强制删除-f
docker container prune 清理所有终止容器
-
拉取镜像
docker search centos 搜索镜像
docker pull ansible/centos7-ansible 拉取镜像
-
私有仓库
#安装运行docker-registry
docker run -d -p 5000:5000 --restart=always --name registry registry
#-v 指定镜像存放路径
- 私有仓库上传、搜索、下载镜像
#标记镜像
docker tag helloworld:V1 127.0.0.1:5000/helloworld:V1
#上传标记镜像
docker push 127.0.0.1:5000/helloworld:V1
#查看镜像信息
curl 127.0.0.1:5000/v2/_catalog
Docker数据管理
- 数据卷
docker volume create my-vol 创建一个数据卷
docker run -P -it --name web --mount source=my-vol,target=/webapp ubuntu:18.04 /bin/bash 启动一个挂载数据卷的容器
docker inspect web 查看数据卷的具体信息
docker volume rm my-vol 删除数据卷
docker volume prune 去拿过来无主的数据卷
- 挂载主机目录
docker run -it --name web --mount type=bind,source=/home/docker,target=/webapp ubuntu:18.04 /bin/bash
默认读写 可--mount type=bind,source=/home/docker,target=/webapp,readonly 配置只读
- 应用
#记录容器内的操作日志
docker run --rm -it --mount type=bind,source=$HOME/.bash_history,target=/root/.bash_history ubuntu:18.04 bash
Docker 网络
-
外部访问容器
-p 指定端口映射 -p 8080:80 -P会随机映射一个49000~49900
-
映射所有接口地址
-p 5000:5000
-
映射到指定地址的指定端口
-p 127.0.0.1:5000:5000
-
映射指定地址的任意端口
-p 127.0.0.1::5000
-p 127.0.0.1:5000:5000/udp 标记指定udp端口
-
查看映射端口配置
docker port nostalgic_morse 5000
-
容器互联
-
新建网络
docker network create -d bridge my-net
-
连接容器
docker run -it --rm --name test01 --network my-net centos:7 /bin/bash
docker run -it --rm --name test02 --network my-net centos:7 /bin/bash
- 配置 DNS
cat /etc/docker/daemon.json "dns": [ "119.29.29.29". "114.114.114.114" ] #设置主机名 -h name docker run -h testname #设置dns --dns=119.29.29.29 docker run --dns=119.29.29.29 #配置dns搜索域 --dns-search=west.cn docker run --dns-search=west.cn
- 高级网络配置
docker启动时 --> 会在主机自动创建一个docker0虚拟网桥(bridge 软件交换机) 一端eth0 另外一端是vethXXXX
- 快速配置指南
-b 指定容器挂载的网桥 --bip=CIDR 定制docker0的掩码 -H SOCKET docker服务端接收命令的通道 --icc=true|false 是否支持容器间通信 --ip-forward=true|false --iptables=true|false 是否运行docker添加iptables规则 --mtu=BYTES 容器网络中MTU --dns=223.5.5.5 --dns-search=west.cn -h hostname --link=CONTAINER_NAME:ALIAS 添加到另外一个容器的连接 --net=bridge|none|container:NAME_OR_ID|host 配置容器桥接模式 -p SEPC 映射容器端口到宿主主机 -P 映射容器所有端口到宿主主机
- 容器访问控制
#容器访问外部网络 #打开系统转发 cat /etc/sysctl.conf net.ipv4.ip_forward=1 #容器之间访问 #所有容器都会被连接到docker0网桥上 #本地系统防火墙是否运行通过 #访问所有端口 默认情况下,不同容器之间是允许网络互通 为了安全,可在/etc/docker/daemon.json配置"icc": false
- 访问指定端口
-icc=false 关闭网络访问后 还可通过 --link=CONTAINER_NAME:ALIAS 访问容器开放端口
-
-
配置docker0网桥
docker服务默认会创建一个docker0网桥 还给docker0网桥设置IP地址和子网掩码
-
自定义网桥
#删除旧网桥 yum install -y bridge-utils systemctl stop docker ip link set dev docker0 down brctl delbr docker0 #创建一个网桥 brctl addbr bridge0 ip addr add 192.168.5.1/24 dev bridge0 ip link set dev bridge0 up #在/etc/docker/daemon.json配置 "bridge": "bridge0"
Compose
-
安装
yum install -y docker-compose
-
例子
mkdir -p /root/mypython cd /root/mypython cat app.py from flask import Flask from redis import Redis app = Flask(__name__) redis = Redis(host='redis', port=6379) @app.route('/') def hello(): count = redis.incr('hits') return 'Hello World! 该页面已被访问 {} 次。\n'.format(count) if __name__ == "__main__": app.run(host="0.0.0.0", debug=True) cat Dockerfile FROM python:3.6-alpine ADD . /code WORKDIR /code RUN pip install redis flask CMD ["python", "app.py"] cat docker-compose.yml version: '3' services: web: build: . ports: - "5000:5000" redis: image: "redis:alpine" #运行compose项目 docker-compose up
-
命令
#命令选项 -f 指定使用的compose模板文件 默认docker-compose.yml -p 指定项目名称 默认使用目录名作为项目名称 --x-networking 使用docker的可插拔网络后端特性 --x-networking-driver DRIVER 指定网络后端的驱动 默认bridge --verbose 输出更多调试信息 -v 打印版本并退出 #命令使用 build 构建项目中服务容器 --force-rm 删除构建过程中的临时容器 --no-cache 构建过程中不使用cache --pull 始终尝试通过pull获取新版本的镜像 config 检查compose文件格式是否正确 down 停止up命令所启动的容器并移除网络 exec 进入指定的容器 images 列出compose文件中包含的镜像 kill -s参数指定发送的信号 docker-compose kill -s SIGINT 强制停止所有容器 logs 查看服务容器的输出 pause 暂停一个服务容器 port 输出某个容器端口锁映射的公共端口 ps 列出项目中目前所有容器 -q参数 只打印容器ID信息 pull 拉取服务依赖的镜像 --ignore-pull-failures 忽略拉取过程中的错误 push 推送服务依赖的镜像到docker镜像仓库 restart 重启项目中的服务 rm 删除所有服务容器 run 在指定服务商执行命令 scale 设置指定服务运行的容器个数 docker-compose scale web=3 db=2 start 启动已经存在的服务容器 stop 停止已经处于运行状态的容器 top 查看各个服务容器内的运行的进程 unpause 恢复暂停中的服务 up 自动完成包括构建镜像 创建服务 启动服务
-
compose模板文件
build Dockerfile所在文件夹的路径 cap_add cap_drop 指定容器内核能力分配 #拥有所有能力 cap_add: - ALL #去掉NET_ADMIN能力 cap_drop: - NET_ADMIN command 覆盖容器启动后默认执行命令 command: echo "hello world" configs 仅用于swarm mode cgroup_parent 指定父cgroup 继承改组的资源限制 container_name 指定容器名称 deploy 仅用于swarm node devices 指定设备映射关系 depends_on 解决容器依赖 启动先后 services: web: build: . depends_on: - db - redis dns 自定义dns dns: 114.114.114.114 dns: - 8.8.8.8 - 114.114.114.114 dns_search 配置dns搜索域 tmpfs 挂载一个tmpfs文件系统到容器 env_file 从文件中获取环境变量 environment 设置环境变量 expose 暴露端口 但不映射到宿主机 external_links extra_hosts 指定额外的host名称映射信息 healthcheck 通过命令检查容器是否正常运行 image 指定镜像名称或镜像ID labels 为容器添加元信息 logging 配置日志选项 network_mode 设置网络模式 networks 配置容器连接的网络 pid ports 暴露端口信息 secrets 储存敏感数据 security_opt 配置标签的用户名和角色名 stop_signal 设置另外一个信号来停止容器 sysctls 配置容器内核参数 ulimits 指定容器的限制值 volumes 配置挂载数据卷 HOST:CONTAINER:ro volumes: - /var/lib/mysql/:ro
-
例子
mkdir -p /root/mydjango cd /root/mydjango cat Dockerfile FROM python:3.6-alpine ENV PYTHONUNBUFFERED 1 WORKDIR /code ADD . /code/ RUN pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/ cat docker-compose.yml version: '3' services: web: build: . command: python3 manage.py runserver 0.0.0.0:8080 volumes: - .:/code ports: - "8080:8080"
Docker Machine
-
安装
curl -L https://github.com/docker/machine/releases/download/v0.16.2/docker-machine-
uname -s
-uname -m
>/tmp/docker-machine && chmod +x /tmp/docker-machine && sudo cp /tmp/docker-machine /usr/local/bin/docker-machine -
使用
active 查看活跃的docker主机 config 输出连接的配置信息 create 创建一个docker主机 env 显示连接某主机需要的环境变量 inspect 获取主机更多信息 ip 获取主机地址 kill 停止某主机 ls 列出所有管理的主机 provision 重新设置一个已存在的主机 regenerate-certs 为某个主机重新生成TLS认证信息 restart 重启主机 rm 删除某台主机 ssh SSH到主机上执行命令 scp 在主机之间复制文件 mount 挂载主机目录到本地 start 启动主机 status 查看主机状态 stop 停止主机 upgrade 更新主机docker版本为最新 url 获取主机URL version 输出docker-machine版本信息 help 输出帮助信息
Docker Swarm
-
Swarm 集群管理编排工具
docker swarm
-
初始化集群
#初始化 docker swarm init --advertise-addr 172.16.7.127 #增加工作节点 docker swarm join --token xxxxxx 172.16.7.127:2377 #查看集群 docker node ls
-
部署服务
#新建服务 docker service create --replicas 3 -p 80:80 --name nginx nginx:V3 #查看服务 docker service ls #查看某个服务的日志 docker service logs nginx #服务伸缩 #增加 docker service scale nginx=8 #减少 docker service scale nginx=2 #删除服务 docker service rm nginx
-
Swarm集群使用compose文件
version: '3' services: wordpress: image: wordpress ports: - 80:80 networks: - overlay environment: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: wordpress deploy: mode: replicated replicas: 3 db: image: mysql networks: - overlay volumes: - db-data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: somewordpress MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: wordpress deploy: placement: constraints: [node.role == manager] visualizer: image: dockersamples/visualizer:stable ports: - 8080:8080 stop_grace_period: 1m30s volumes: - "/var/run/docker.sock:/var/run/docker.sock" deploy: placement: constraints: [node.role == manager] volumes: db-data: networks: overlay: #部署服务 docker stack deploy -c docker-compose.yml wordpress #查看服务 docker stack ls #移除服务 docker stack down 服务名
-
Swarm集群管理敏感数据
#创建secret openssl rand -base64 20 | docker secret create mysql_password - #查看secret docker secret ls
-
创建MySQL服务
docker network create -d overlay mysql_private docker service create \ --name mysql \ --replicas 1 \ --network mysql_private \ --mount type=volume,source=mydata,destination=/var/lib/mysql \ --secret source=mysql_root_password,target=mysql_root_password \ --secret source=mysql_password,target=mysql_password \ -e MYSQL_ROOT_PASSWORD_FILE="/run/secrets/mysql_root_password" \ -e MYSQL_PASSWORD_FILE="/run/secrets/mysql_password" \ -e MYSQL_USER="wordpress" \ -e MYSQL_DATABASE="wordpress" \ mysql:latest docker service create \ --name wordpress \ --replicas 1 \ --network mysql_private \ -p 3000:80 \ --mount type=volume,source=wpdata,destination=/var/www/html \ --secret source=mysql_password,target=wp_db_password,mode=0400 \ -e WORDPRESS_DB_USER="wordpress" \ -e WORDPRESS_DB_PASSWORD_FILE="/run/secrets/wp_db_password"\ -e WORDPRESS_DB_HOST="mysql:3306" \ -e WORDPRESS_DB_NAME="wordpress" \ wordpress:latest
-
Swarm集群中管理配置数据
#新建redis.conf文件 cat redis.conf port 6380 #创建config docker config create redis.conf redis.conf #查看config docker config ls #创建redis服务 docker service create \ --name redis \ --config redis.conf \ -p 6379:6380 \ redis:latest \ redis-server /redis.conf
-
Swarm mode与滚动升级
#之前已通过命令创建nginx服务 docker service create --name nginx --replicas 2 -p 80:80 nginx:1.13.7-alpine #升级 docker service update \ --image nginx:1.13.12-alpine \ nginx #回滚 docker service rollback nginx
-
etcd集群
version: '3' networks: byfn: services: etcd1: image: quay.io/coreos/etcd container_name: etcd1 command: etcd -name etcd1 -advertise-client-urls http://0.0.0.0:2379 -listen-client-urls http://0.0.0.0:2379 -listen-peer-urls http://0.0.0.0:2380 -initial-cluster-token etcd-cluster -initial-cluster "etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380" -initial-cluster-state new ports: - 2379 - 2380 networks: - byfn etcd2: image: quay.io/coreos/etcd container_name: etcd2 command: etcd -name etcd2 -advertise-client-urls http://0.0.0.0:2379 -listen-client-urls http://0.0.0.0:2379 -listen-peer-urls http://0.0.0.0:2380 -initial-cluster-token etcd-cluster -initial-cluster "etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380" -initial-cluster-state new ports: - 2379 - 2380 networks: - byfn etcd3: image: quay.io/coreos/etcd container_name: etcd3 command: etcd -name etcd3 -advertise-client-urls http://0.0.0.0:2379 -listen-client-urls http://0.0.0.0:2379 -listen-peer-urls http://0.0.0.0:2380 -initial-cluster-token etcd-cluster -initial-cluster "etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380" -initial-cluster-state new ports: - 2379 - 2380 networks: - byfn #查看集群状态 docker exec -t etcd1 etcdctl member list #etcd操作 #set 设置值 etcdctl put /testdir/testkey "Hello world" #put 更新值 etcdctl update /testdir/testkey "Hello world 666" #get 获取值 etcdctl get /testdir/testkey #更多命令可查--help etcdctl --help
-
k8s
#快速上手 #启动etcd服务 docker run --net=host -d gcr.io/google_containers/etcd:2.0.9 /usr/local/bin/etcd --addr=127.0.0.1:4001 --bind-addr=0.0.0.0:4001 --data-dir=/var/etcd/data