Docker 入门学习笔记

作者 Marlous 日期 2018-10-23
Docker 入门学习笔记

参考:
1、 Docker 菜鸟教程
2、 Docker_入门?只要这篇就够了!(纯干货适合0基础小白)
3、 参考文章

一 Docker 概念与作用

  • “Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。”

  • 制造镜像前,就要服务的软件都装好,镜像运行时进行的任何修改都只是在内存的虚拟文件系统里,删除此容器,所有运行时的修改都丢失。/ 可以在容器基础上制作成镜像,下次用这个镜像运行一个容器。

  • 开发、测试、上线(运维)过程中,将环境打包到容器中,方便部署,开箱即用;
    可以直接使用现成的容器(打包好的环境);
    可以制作自己的容器。

二 安装运行

  1. 去 Docker 官网下载安装包安装。下载前需要注册,因为注册用的 Google 人机验证,所以可能无法显示点击 sign up 按钮。

  2. Docker for Windows Installer(需要 Windows 10 专业版本或企业版,具体见官网。)使用的是微软的 hyper-V,由于 Hyper-V 与 VirtualBox 冲突导致安装上无法使用的情况(如果安装过 virtualbox,32 位的可以和 Hyper-V 共存),可换为 DockerToolbox,后者利用 virtualbox。/ 补充 Ubuntu 安装:

    1
    2
    3
    4
    5
    6
    apt install docker.io
    systemctl unmask docker.service
    systemctl unmask docker.socket
    systemctl start docker.service
    sudo groupadd docker // 创建 docker 用户组,一般已经建好
    sudo usermod -aG docker $USER // 添加 用户到用户组
  3. Tips:
    点击 Docker Quickstart Terminal,如果先安装过 git,会出现 “windows 正在查找 bash.exe” 问题,是因为快捷方式路径不对,因为需要 Git bash.exe 来执行 docker star.sh(git bash 是 Windows 下的命令行工具,基于 msys GNU 环境)。
    快捷方式目标的正确路径书写示例:"D:\Program Files\Git\bin\bash.exe" --login -i "C:\Program Files\Docker Toolbox\start.sh"

  4. 修改 Docker 源:

    1
    2
    3
    4
    5
    6
    7
    8
    修改 Windows 上 Docker 的镜像源:
    Windows 命令行执行 docker-machine ssh [machine-name] 进入 VM bash。

    sudo vi /var/lib/boot2docker/profile

    在 --label provider=virtualbox 的下一行添加 --registry-mirror http://141e5461.m.daocloud.io

    重启 docker 服务:sudo /etc/init.d/docker restart 或者重启 VM:exit 退出 VM bash,在 Windows 命令行中执行 docker-machine restart

三 Docker

1 虚拟化种类

  • 全虚拟化:应用程序实现。
    全虚拟化

  • OS 层虚拟化:
    OS 层虚拟化

  • 硬件层虚拟化:
    硬件层虚拟化

2 Docker 原理与组成

  1. 组成:Docker Client 客户端、Docker Daemon 守护进程、Docker Image 镜像、Docker Container 容器。

  2. 原理:容器技术类似 OS 层虚拟化(不等同),容器本质上是基于应用的,虚拟出运行环境。容器相当于一个个运行的小操作系统,但它是共享宿主机操作系统内核的。

  3. 架构:C/S 架构。客户端提供交互界面,与守护进程(服务程序)交互,运行一个镜像的实例(容器)。
    架构

3 Docker 使用场景

Docker 使用场景

4 Docker 的使用方式

  1. CI/CD 与 DevOps:
    CI/CD 与 DevOps 1
    CI/CD 与 DevOps 2
    CI/CD 与 DevOps 3

四 Docker 快速上手

参考资料

1 基本命令

  1. 镜像操作:
1
2
3
4
5
6
7
8
9
10
11
12
13
# 列出镜像
docker images

# 搜索镜像
docker search

# 拉取镜像,docker hub 中拉取(下载)
docker pull

# 删除镜像
docker rmi 镜像ID
# 删除全部镜像
docker rmi `docker images -q`
  1. 容器操作:
1
2
3
4
5
# 查看正在运行的容器
docker ps
-a # 参数查看全部
-l # 参数查看最后一次运行的
-f status=exited # 查看停止的
  1. 创建与启动容器:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
docker run
-i # 运行容器
-t # 启动后进入命令行
-it
--name=名称 # 为创建的容器命名
-d # 后台启动(启动后不进去)。
-v # 目录映射,前者为宿主机目录,后者为容器目录。通过宿主机操作容器,--v 可做多个映射。
-p # 端口映射,前者为宿主机端口,后者为容器端口。 --p 做多个端口映射。

# 退出容器、重启、进入
exit

使用 docker restart 命令重启容器
使用 docker attach 命令进入容器

------------------------------------------------------------------------
交互式容器启动:进容器运行,退出停止运行。
docker run -it --name=起个容器名 镜像名:标签 [命令解释器路径]

守护式容器启动:
docker run -id --name=起个容器名 镜像名:标签
docker exec -it 容器名 # 进入守护式容器
先按 ctrl+p,再按 ctrl+q # 退出,容器后台运行

-------------------------------------------------------------------------
docker start # 运行容器
docker stop # 停止容器
  1. 文件拷贝:

    1
    2
    docker cp 源文件目录 容器名:容器目录
    docker cp 容器名:容器目录 目标文件目录
  2. 目录挂载:

    1
    2
    docker run -di --name=容器名 -v 宿主机目录路径:容器内目录路径 镜像名称:标签
    --priviledged=true # 获取特权,访问共享的目录
  3. 查看 IP 地址与删除容器

    1
    2
    3
    docker inspect 容器名

    docker rm 容器名
  4. 进入运行的容器方法:
    参见 进入正在运行的Docker容器的4种方式。(在 VSCode 中使用更方便。)

  • 使用 docker attach
  • 使用 SSH
  • 使用 nsenter
  • 使用 exec
  1. 目录映射与数据卷:
  • 目录映射与数据卷:卷由 Docker 引擎进行管理维护的。数据卷默认可能会保存于 /var/lib/docker/volumes。/ 挂载目录属于用户自行维护。你就必须手动处理所有权限问题。

  • 通过挂载数据卷或挂载目录都可以实现数据永久化(容器运行结束不会保存数据,比如 mysql 数据、一些配置),但使用数据卷,其支持的特性会更好。

  • 将本地目录挂载到容器中:

    1
    2
    3
    示例:
    # -v 用来将宿主机目录挂载到容器中,`:` 前面是宿主机目录,后面是容器目录
    docker run -itd -p 80:80 --link php:php -v /www/html:/usr/local/nginx/html --name=nginx nginx
  1. 容器的数据卷(数据的永久化):
  • 容器的数据卷概念:
    容器的数据卷是一个本地主机上的目录。/ 利用 docker 数据卷映能保证镜像再次运行的时候数据不会丢失、映射了目录也更方便的传数据到运行的 docker 容器里。
    容器的数据卷概念

  • 对数据卷的操作:
    参见 Docker : 数据卷(创建、挂载、查看、删除)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    创建:
    docker volume create test_lamp_www # apache的web根目录 / 容器内:/var/www
    docker volume create test_lamp_apache_conf # apache的配置目录 / 容器内:/etc/apache2
    docker volume create test_lamp_mysql_conf # MySQL的配置目录 / 容器内:/etc/mysql
    docker volume create test_lamp_mysql_data # MySQL的数据目录 / 容器内:/var/lib/mysql

    查看所有:
    docker volume ls

    查看某个具体的:
    docker volume inspect test_lamp_www

    挂载数据卷:
    docker run -it -p 80:80 -p 3306:3306 -v test_lamp_www:/var/www -v test_lamp_apache_conf:/etc/apache2 -v test_lamp_mysql_conf:/etc/mysql -v test_lamp_mysql_data:/var/lib/mysql --name testproject mattrayner/lamp /bin/bash
    # 解释:
    # docker run:运行一个 container,如果后面要绑定宿主主机的 0-1024 端口需要使用 sudo
    # -p port1:port2: 将宿主机的端口 port1 映射到容器中的 port2
    # -v volume:path: 将宿主机的 docker 卷映射到容器中的指定的路径
    # -t -i mattrayner/lamp /bin/bash:使用 mattrayner/lamp 生成容器,并打开 shell

    删除数据卷:
    docker volume rm test_lamp_www
  • Windows 环境中 DockerToolBox 目录挂载问题:
    DockerToolBox 的工作原理是,首先通过 VM 虚拟机创建一个 Linux 虚拟机,然后在虚拟机中安装 Docker。然后 VM 虚拟机通过共享文件夹的机制将宿主机文件挂载到虚拟机中,然后我们通过 -v 参数挂载时,: 前面的目录应该是 Linux 虚拟机中的共享文件夹的目录。

  1. 数据卷容器:
  • 数据卷容器是一个容器。/ 也就是使用 –volumes-from 的东西。这早就不用了,如果看了书还在说这种方式,那说明书已经过时了。按照今天的理解,这类数据容器,无非就是挂了个匿名卷的容器罢了,详见
    数据卷容器概念
  1. 数据卷的备份、迁移与使用:
    直接对宿主机本地的数据卷进行备份、转移、挂载到容器上。

  2. 容器的网络问题:

  • 原理:
    原理

  • 功能:
    可以更改 docker0 的网络地址网段,也可以在宿主机添加虚拟网卡给 docker 容器。

  • docker 容器间链接:
    默认是可以相互连接的。重启容器 IP 可能会发生变化。/ 容器启动时的 link 选项来避免 IP 变化的不可靠连接。/ 更改 docker 配置文件来禁止容器间的连接。/ 允许特定容器间的链接:docker 配置将 --c=false --iptables=true、容器启动加 link 参数。

  • docker 与外部网络连接:
    docker 配置文件中 --ip-forward=true 默认转发流量;配置 iptables:表(每个环节中的 nat 等表)、链(数据流向)、操作(对每个节点的操作,如拒绝、接受)。通过添加 iptables 规则来控制对特定容器的拒绝接受访问。
    docker 与外部网络连接

  • docker 的跨主机连接:
    使用 open vswitch 虚拟网桥(建立网桥、配置接口、分网段)、weave 开源专用于 docker 跨主机连接软件。
    docker 的跨主机连接

2 制作、备份与迁移

  1. 制作镜像:
  • 将容器制作为镜像:

    1
    docker commit 容器名 起个镜像名
  • 用 dockerfile 构建一个镜像:类似于安装脚本。
    选一个空目录;编写 dockerfile; 在 Dockerfile 文件所在目录执行构建命令。
    参考博文 1 参考博文 2

  1. 镜像备份:
    备份及恢复(导出导入)的镜像都在宿主机执行 docker 命令所在位置。

    1
    docker save -o 压缩包名.tar 镜像名
  2. 镜像恢复:
    备份及恢复(导出导入)的镜像都在宿主机执行 docker 命令所在位置。

    1
    docker load -i 压缩包名.tar

3 部署运行实例

实例:部署运行 MySql

  1. 获取镜像:
  • 通过 pull 镜像:

    1
    2
    3
    docker search mysql
    docker pull mysql:5.6
    docker images |grep mysql
  • 使用容器保存的镜像。

  • 通过 Dockerfile 构建镜像:参考文章
    用 Dockerfile 脚本做镜像的定制,实际上就是定制每一层所添加的配置、文件。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    进入创建的 mysql 目录,创建 Dockerfile
    编写脚本。
    docker build -t mysql

    ---------------------------------------------------------
    # 先创建准备存放文件的文件夹
    mkdir -p ~/mysql/data ~/mysql/logs ~/mysql/conf

    data 目录将映射为 mysql 容器配置的数据文件存放路径
    logs 目录将映射为 mysql 容器的日志目录
    conf 目录里的配置文件将映射为 mysql 容器的配置文件

    然后使用制作好的镜像。
  1. 使用镜像:
    1
    2
    3
    4
    5
    6
    7
    8
    docker run -p 3306:3306 --name [mymysql] -v [$PWD/conf:/etc/mysql/conf.d] -v [$PWD/logs:/logs] -v [$PWD/data:/var/lib/mysql] -e [MYSQL_ROOT_PASSWORD=123456] -d [mysql:5.6]

    # 参数
    -p 3306:3306:将容器的 3306 端口映射到主机的 3306 端口。
    -v -v $PWD/conf:/etc/mysql/conf.d:将主机当前目录下的 conf/my.cnf 挂载到容器的 /etc/mysql/my.cnf。
    -v $PWD/logs:/logs:将主机当前目录下的 logs 目录挂载到容器的 /logs。
    -v $PWD/data:/var/lib/mysql :将主机当前目录下的data目录挂载到容器的 /var/lib/mysql 。
    -e MYSQL_ROOT_PASSWORD=123456:初始化 root 用户的密码。

五 Dockerfile 与 docker-compose

参考:
1、 Dockerfile 构建
2、 Docker与Dockerfile极简入门文档
3、 dockerfile 和 docker-compose 的关系
4、 docker-compose教程(安装,使用, 快速入门)

1 概念

  • Dockerfile 是定义镜像(单个镜像构建的脚本)。/ docker-compse.yml 是以启动 container 为目的的是多个镜像构建文件(项目需要哪些镜像,每个镜像怎么配置,要挂载哪些 volume,等等信息都包含在 docker-compose.yml 里,取代 run 命令,用 docker-compose 命令运行)。

  • 如果你想要从一个基础镜像开始建立一个自定义镜像,可以选择一步一步进行构建,也可以选择写一个配置文件,然后一条命令(docker build)完成构建,显然配置文件的方式可以更好地应对需求的变更,这个配置文件就是 Dockerfile。/ 相比 image 这种黑盒子,Dockerfile 这种显而易见的脚本更容易被使用者接受,它明确的表明 image 是怎么产生的。有了 Dockerfile,当我们需要定制自己额外的需求时,只需在 Dockerfile 上添加或者修改指令,重新生成 image 即可,省去了敲命令的麻烦。

  • 团队采用三个 Dockerfile,一个负责开发环境的镜像构建,一个负责预发布,一个负责生产环境的镜像构建。
    开发镜像包含了代码构建所需要的环境,镜像大小自然比较大,生产镜像仅包含应用运行所需要的内容,是很精简的体积很小的镜像。

2 编写

  1. 怎样编写:
  1. 示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
Dockerfile 编写
同文件夹中,docker build -t lamp_auto 构建
*/

# LAMP docker image
FROM ubuntu
MAINTAINER Marlous "goonecat@foxmail.com"

RUN apt-get update && apt-get install vim-gtk && apt-get install apache2 && apt-get install php && apt-get install mysql-server && apt-get install phpmyadmin

# MySQL 服务启动报错的话(No directory, logging in with HOME=/)
RUN usermod -d /var/lib/mysql/ mysql && ln -s /var/lib/mysql/mysql.sock /tmp/mysql.sock && chown -R mysql:mysql /var/lib/mysql && chmod 777 /var/www

RUN apt-get install libapache2-mod-php && apt-get install php7.2-mbstring && apt-get install php7.2-mysql && apt-get install php7.2-gd && ln -s /usr/share/phpmyadmin /var/www/

RUN apt install python-setuptools && apt-get install supervisor

EXPOSE 80 3306
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
docker-compose 编写
同文件夹中,docker-compose up -d 运行
*/

lamp_auto:
image: 'lamp_auto'
restart: always
hostname: 'lamp_auto'
ports:
- '3306:3306'
- '80:80'
volumes:
- 'docker volume create test_lamp_www'
- 'docker volume create test_lamp_apache_conf'
- 'docker volume create test_lamp_mysql_conf'
- 'docker volume create test_lamp_mysql_data'

3 使用方法

  1. 构建并使用 docker-compose 运行容器:
  • 可以使用 Docker Hub 上的或本地存在的镜像。src 放制作镜像用到的东西,可以没有。
  • Web 文件夹内的 Dockerfile 是构建 LAMP 环境的(没有 MySQL)。
  • MySQL 文件夹内的 Dockerfile 是构建 MySQL 镜像的。
  • 这个 docker-compose.yml 是配置,描述了怎么样建立数据卷、怎样连接两个容器,怎样运行容器等。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
使用流程:
编写 Dockerfile。
编写 docker-compose.yml。
进入并在 docker 文件夹中运行命令 docker-compose up -d,运行整个项目。
*/

project/
|- src/
|- docker/
|- Web/
| |- Dockerfile
|- MySQL/
| |- Dockerfile
|- docker-compose.yml
  1. 需要的镜像已存在,使用 docker-compose 运行容器:
1
2
3
4
5
6
7
8
/*
使用流程:
编写 docker-compose.yml。
进入并在 docker 文件夹中运行命令 docker-compose up -d,运行整个项目。
*/

project/
|- docker-compose.yml