Docker

一句话:操作系统层面的虚拟化技术, 相比于传统虚拟机,优点多。 基本概念:

  • 镜像(Image) 相当于一个root文件系统
  • 容器(Container) 是镜像的实例,本质是进程
  • 仓库(Repository)

主要分为CE和EE版本 添加内核参数

WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled

$ sudo tee -a /etc/sysctl.conf <<-EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
$ sudo sysctl -p

镜像加速器

vim /etc/docker/daemon.json
{
  "registry-mirrors": [
    "https://registry.docker-cn.com"
  ]
}
sudo systemctl daemon-reload
sudo systemctl restart docker

使用场景

  • 本地依赖
  • 搭建环境
  • 微服务
  • 自动测试
  • 部署过程
  • 持续部署
  • 多租户环境
  • 单机多服务
  • 扩容QPS

好处

  • 保证线上线下环境一致
  • 简化部署流程
  • 实现沙盒机制,与操作系统隔离开
  • 实现模块化
  • 实现虚拟化

基本命令

$ docker -v
$ docker info

$ docker ps -a # 查看正在运行的容器
$ docker kill $(docker ps -a -q) # 杀死所有正常运行的容器
$ docker rm $(docker ps -a -q) # 删除所有已经停止的容器
¥ docker rmi $(docker images -q -f dangling=true) # 删除所有未打 dangling 标签的镜像
$ docker rmi $(docker images -q) # 删除所有镜像
$ docker logs

镜像

操作系统分为内核和用户空间。对于 Linux 而言,内核启动后,会挂载 root 文件系统为其提供用户空间支持。而 Docker 镜像(Image),就相当于是一个 root 文件系统。 Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。 使用Union FS技术,分层存储。

常见命令

$ docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]
$ docker pull ubuntu
$ docker image ls # 列出下载的镜像 -a 列出中间层镜像 ubuntu 显示特定
$ docker system df # 查看镜像占用的空间
$ docker image ls -f dangling=true # 显示虚悬镜像
$ docker image prune # 删除虚悬镜像
$ docker image rm <ID> # 删除镜像, 先删除容器,再删除镜像
$ docker run -it --rm ubuntu bash # 运行

# 使用Dockerfile定制镜像
$ vim Dockerfile
FROM nginx # scratch 空白镜像
COPY package.json /usr/src/app/
ADD # 高级copy,会自动解压tar,url会自动下载等
CMD echo $HOME
CMD ["nginx", "-g", "daemon off;"] # nginx 以前台形式运行, 容器内没有后台服务的概念
ENTRYPOINT ["curl", "-s", "http://blog.itswcg.com"] # 可以传参
ENTRYPOINT ["docker-entrypoint.sh"] # 指定脚本
ENV NAME WCG # 变量
VOLUME /data # 挂载目录
EXPOSE 80 # 只是声明端口
WORKDIR # 工作目录
USER  # 用户
HEALTHCHECK # 健康检查
ONBUILD COPY # 当前镜像构建时不会执行,以当前镜像为基础镜像去构建下一级镜像时才执行
RUN apt update \
    && apt install redis \
    && # 尽量一个命令,最后清除不需要的东西

$ docker build -t nginx:v3 . # 构建镜像, .指定上下文目录
$ .dockerignore 文件
$ docker build <url>

容器

容器是镜像运行时的实体,其实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的命名空间。因此容器可以拥有自己的 root文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。 每一个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层,我们可以称这个为容器运行时读写而准备的存储层为 容器存储层。 容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡,因此要使用数据卷,持久化。

常见命令

$ docker run -it ubuntu /bin/bash  # 启动ubuntu并启动一个终端
# -i 让容器的标准输入保持打开 -t 分配一个伪终端并绑定在容器的标准输出上
$ docker container start/restart
$ docker run -d ubuntu # 后台运行
$ docker container ls
$ docker container logs <container id>
$ docker container stop
$ docker exec -it <container id> bash # 后台进入容器
$ docker export <container id> > ubuntu.tar # 导出容器
$ docker import  # 导入容器快照
$ docker container rm # 删除容器 -f 删除一个运行中的容器
$ docker container prune # 清除所有终止的容器
$ docker inspect <container id>  # 查看容器信息

访问仓库

$ docker login/logout
$ docker search
$ docker pull
$ docker tag ubuntu:17.10 itswcg/ubuntu:17.10
$ docker push itswcg/ubuntu:17.10 # push

数据管理

# 数据卷
$ docker volume create my-vol # 创建一个数据卷
$ docker volume ls
$ docker volume inspect my-vol # 查看信息
$ docker run -d -P --name web --mount source=my-vol,target=/webapptraining/webapp python app.py
$ docker volume rm my-vol # 删除
$ docker rm -v  # 删除容器的时候删除数据卷
$ docker volume prune # 清理
$ docker run -dit --mount type=bind, source=/root/test.py, target=/root/test.py

网络

# -p 标记会随机映射49000~49900端口到容器端口
$ docker run -d -p 5000:5000 training/webapp python app.py # 本地=>容器
$ docker port <container id> # 产看端口映射

# 容器互联
$ docker network create -d bridge my-net # 创建新的docker网络
$ docker run -it --rm --name busybox1 --network my-net busyboxsh
$ docker run -it --rm --name busybox2 --network my-net busyboxsh

Docker三剑客

# Compose 定义和运行多个docker容器的应用
# 包含服务和项目 docker-compose.yml
$ docker-compose up # 运行
$ docker-compose build # 构建项目中的容器
$ docker-compose config # 验证配置
$ docker-compose down/kill/logs/pause/port/ps/pull/push/restart/rm/run
$ -d/--name/--entrypoint/-e/-u/--no-deps/--rm/-p/--service-ports/-T
$ docker-compose scale web=3 db=2 # 启动3个容器运行web服务,2个容器运行db
$ docker-compose start/stop/top/unpause
# 启动
$ docker-compose up -d/--no-deps/--force-recreate/--no-recreate/--no-build/-t
$ docker-compose version
$ vim docker-compose.yml
version: "1"
services:
    webapp:
        build: ./build # 指定Dockerfile所在文件夹路径
        image: web/image
        depends_on: # 先启动db再启动web
          - db
          - redis
        redis:
          image: redis
        db:
          image: mysql
        ports:
          - "80:80"
        volumes:
          - "/data"
        env_file: # 从文件中获取环境变量
          - ./common.env
        environment:
          PACK_ENV=develop
        logging:
          driver: syslog
          options:
            syslog-address: "tcp://"
        secrets:
          my_secret:
            file: ./my_secret.txt
        restart: always


# Machine 负责在多个平台上快速安装Docker环境
$ curl -L https://github.com/docker/machine/releases/download/v0.16.0/docker-machine-`uname -s`-`uname -m` >/tmp/docker-machine &&
    chmod +x /tmp/docker-machine &&
    sudo cp /tmp/docker-machine /usr/local/bin/docker-machine
$ docker-machine -v
$ docker-machine create -d virtualbox test # 使用virtualbox驱动创建docker主机
$ docker-machine ls
$ docker-machine env test # 让后续操作对象都是目标主机
$ docker-machine ssh test # 登录ssh


# Swarm 提供docker容器集群服务, 可以将多个docker主机封装为单个大型的虚拟docker主机
# 运行docker主机会初始化一个swarm集群,这样该主机就成为swarm集群的节点
# 分为管理节点和工作节点
$ docker swarm # 只能在管理节点执行
$ docker-machine create -d virtualbox manager # 创建管理节点
$ docker-machine ssh manager
    docker@manager$ docker swarm init # 初始化一个集群
$ docker-machine create -d virtualbox worker1
    docker@worker1$ docker swarm join # 加入集群
$ docker node ls # 查看集群,在管理
$ docker service create --replicas 3 -p 80:80 --name nginx nginx:1.13.7-alpine # 新建服务,在集群中
$ docker service ls
$ docker service ps nginx
$ docker service scale nignx=5 # 扩展容器数量
$ docker service rm nginx # 移除

参考

https://github.com/itswcg/Books/blob/master/docker_practice.epub