Fellow Travellers

Docker笔记

于佳鑫
字数统计: 3.6k阅读时长: 14 min
2018/12/24 Share

一、Docker简介

由于在项目部署的时候经常会出现在本机上运行是好使的,但是部署到服务器上时出现各种问题,而这种问题的原因经常是因为环境的问题,所以Docker出现了。

Docker 是基于Go语言实现的开源项目。

Docker是在Linux容器技术的基础上发展出来的。我们可以将应用运行在Docker容器上,而Docker容器在任何操作系统上都是一致的。

Docker主要通过对应用组件的封装、分发、部署、运行等进行管理,来实现用户的app及其运行环境能够做到一次封装,到处运行

二、Docker的安装

1、安装Docker

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
28
29
30
### Ubuntu

# step 1: 安装必要的一些系统工具
sudo apt-get update
sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common
# step 2: 安装GPG证书
curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
# Step 3: 写入软件源信息
sudo add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
# Step 4: 更新并安装 Docker-CE
sudo apt-get -y update
sudo apt-get -y install docker-ce


# 查看是否安装成功
$ docker -v
>> Docker version 17.12.1-ce, build 7390fc6


### centos7

# step 1: 安装必要的一些系统工具
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# Step 2: 添加软件源信息
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# Step 3: 更新并安装 Docker-CE
sudo yum makecache fast
sudo yum -y install docker-ce
# Step 4: 开启Docker服务
sudo service docker start

2、配置阿里云镜像加速

1)访问网址获取个人的加速器地址

2)按照下面的操作文档进行操作

1
2
3
4
5
6
7
8
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://l7s5cnt9.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

3、hello,world

1
2
# 非管理员用户要加sudo
$ sudo docker run hello-world

mark

4、Docker是怎么工作的

Docker是一个CS结构的系统,Docker的守护进程运行在主机上,客户端通过socket连接与守护进程进行传输命令,守护进程接受命令并管理运行在主机上的容器。

一个主机上可能有多个容器,每个中运行着镜像(tomcat、mysql...)的实例。

5、Docker为什么比虚拟机快

详情请见

(1)由上图可以看出Docker比虚拟机少了抽象层Hypervisor,Docker不需要Hypervisor来实现硬件资源虚拟化,而是直接采用宿主的硬件资源。

(2)而且Docker采用的是宿主机的内核,所以新建一个容器时不需要像虚拟机那样重新加载操作系统内核,从而避免引导、加载系统内核这个耗时的操作。

三、常用命令

1、帮助命令

1
$ docker --help

2、镜像命令

1)查看本地主机中的所有镜像

1
2
3
4
5
6
7
$ sudo docker images

Option:
-a:列出本地所有镜像(包括中间映像层)**
-q:只显示镜像id**
--digests:显示镜像完整的描述信息
--no-trunc:不截断输出

同一个仓库源可以有多个tag,代表这个仓库源的不同版本,所以我们使用REPOSITORY:TAG来定义不同的镜像。

2)从hub上查找镜像

1
2
3
4
5
6
$ sudo docker search 查找镜像名

Option:
--no-trunc:不截断输出
-s 数字:列出星星不小于指定值的镜像
--automated:列出自动构建类型的镜像

3)下载镜像

1
2
# 版本号默认为lastest,最新版本
$ sudo docker pull 下载的镜像名:[版本号]

4)删除镜像

1
2
3
4
5
6
7
8
$ sudo docker rmi 某个镜像的id

# 强制删除,当镜像被某个容器使用时,无法被删除
$ sudo docker rmi -f 某个镜像的id
# 删除多个镜像
$ sudo docker rmi 镜像id1 镜像id2...
# 删除全部镜像
$ sudo docker rmi -f $(docker images -qa) # 查出本机所有镜像的id

3、容器命令

1)新建并启动容器

1
2
3
4
5
6
7
8
9
10
11
12
13
$ sudo docker run 镜像id

Option:
--name="想要给容器起的名字":设置容器名(可以不用写,会自动生成)
-d:在后台运行容器,也称守护式容器**
-i:以交互式运行容器,通常与-t同时使用**
-t:为容器分配一个伪终端,常与-i同时使用**
-P:随机端口映射
-p:指定端口映射,主要有以下4种格式
ip:hostPort:containerPort
ip::containerPort
hostPort:containerPort**
containerPort

启动交互式容器

2)列出Docker中有哪些容器在运行

1
2
3
4
5
6
7
8
$ sudo docker ps

Option:
-a:列出所有运行的容器(正在运行+历史运行)
-l:显示最近创建的容器
-n 数字:显示指定数字创建的容器
-q:静默模式,只显示容器编号**
--no-trunc:不截断输出

3)退出交互式容器

1
2
3
4
# 容器停止退出
exit
# 容器不停止退出
Ctrl+P+Q

4)其他操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 启动容器,将已经停止的容器启动
$ sudo docker start 容器id

# 重启容器
$ sudo docker restart 容器id

# 停止容器
$ sudo docker stop 容器id

# 强制停止容器
$ sudo docker kill 容器id

# 删除已经停止的容器
$ sudo docker rm 容器id

# 强制删除所有容器(不管是否停止)
$ sudo docker rm -f $(docker ps -aq)
$ sudo docker ps -aq | xargs docker rm

5)守护式启动

1
2
# 上面说过了,使用-d命令启动,下面介绍注意点
$ sudo docker run -d 镜像id

由上图发现,我们运行的容器已经退出。

这个是Docker机制的问题,由于我们启动的容器中没有前台进程,而是以后台进程的形式运行的,Docker就会以为它没事干,于是就将其杀死。

解决方案:

1
2
3
# 1.如果本地镜像只有一个版本,可以直接使用仓库源的名字
# 2.这句命令的含义是:运行一个容器,使用/bin/sh执行后面的shell脚本
$ sudo docker run -d centos /bin/sh -c "while true;do echo hello x5456;sleep 2;done"

6)查看容器日志

查看容器内运行的进程

1
2
3
4
5
6
$ sudo docker logs 容器编号

Option:
-t:加入时间戳
-f:跟随最新的日志打印
--tail 数字:显示指定数字内些条

7)查看容器内部细节

1
2
# 以json格式进行显示
$ sudo docker inspect 容器id

8)进入正在运行的容器并以命令行交互

1
2
3
4
5
6
# 容器中启动新的终端并执行命令,返回
# 如果不写后面的shell脚本,则会启动新的终端
$ sudo docker exec -it 容器id shell脚本

# 直接进入容器,不启动新的终端
$ sudo docker attach 容器id

9)拷贝容器中的文件到本地

1
$ sudo docker cp 容器id:容器中文件的位置 要copy到本地的位置

四、Docker镜像

镜像是一种轻量级、可执行的独立软件包,**用来打包软件运行环境和机基于运行环境开发的软件**,它包括某个软件所需要的所有内容(代码、库、环境变量、配置文件...)

1、UnionFS联合文件系统

联合文件系统是一种分层、轻量级、高性能的文件系统,它可以一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。

Docker的镜像基于UnionFS,也是由一层一层的文件系统组成。

就像我们拉镜像的时候,实际上下载了多层。

为啥tomcat会辣么大??

mark

采用这种分层结构的好处

  • 最大的一个好处就是——共享资源

比如:有多个进行都是从相同的A镜像构建而来,那么宿主机只需要在磁盘上保存一份A镜像,内存中只需要加载一份A镜像,就可以为所有容器服务了。

2、生成镜像Demo

1.从Hub上下载tomcat镜像到本地并运行

1
2
#                 对外暴露端口 内部使用端口
$ sudo docker run -it -p 8888:8080 tomcat

2.故意删除tomcat容器的文档

mark

3.以当前运行的tomcat作为模板,提交生成新的镜像

1
2
3
$ sudo docker commit -a="作者" -m="描述信息" 容器id 要创建的镜像名:[标签名]
# eg.
$ sudo docker commit -a="x5456" -m="del tomcat docs" 70c6fc38df47 x5456/tomcat:2.0

4.启动我们生成的镜像

五、Docker的数据管理

部分参考于:这里

生产环境中使用Docker的过程中,容器中会产生数据,如果不通过commit命令生成一个新的镜像,当容器删除后,其中数据就没有了,所以我们往往需要对数据进行持久化,或者需要在多个容器之间进行数据共享,这必然涉及容器的数据管理操作。

容器中管理数据主要有两种方式:

  1. 数据卷(Data Volumes):容器内数据直接映射到本地主机环境;如何在容器内创建数据卷,并且把本地的目录或文件挂载到容器内的数据卷中。
  2. 数据卷容器(Data Volume Containers):使用特定容器维护数据卷。如何使用数据卷容器在容器和主机、容器和容器之间共享数据,并实现数据的备份和恢复。

1、数据卷

1)使用命令添加

1
2
3
4
5
6
7
$ sudo docker run -v 宿主机绝对路径:容器内目录 镜像id/镜像名

# 这样宿主机和容器中的这两个目录就联系起来了
$ sudo docker run -v /myData:/ContainerData centos

# 可以在目录后面加上:ro表示只读,这样有:ro的内个目录就只有read权限
$ sudo docker run -v /myData:/ContainerData:ro centos

2)采用DockerFile进行添加

1.书写DockerFile文件dockerfile2

1
2
3
4
FROM centos
VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
CMD echo "finished,--------success1"
CMD /bin/bash

2.使用命令生成镜像

1
$ sudo docker build -f dockerfile2 -t x5456/centos .

3.由于我们上面命令没有指定宿主机的位置,所以我们需要查看容器详细信息

1
$ sudo docker inspect 724f7b7a9793

2、数据卷容器

如果用户需要在**多个容器之间共享一些持续更新的数据**,最简单的方式是使用数据卷容器。数据卷容器也是一个容器,但是它的目的是专门用来提供数据卷供其他容器挂载。

1.创建一个数据卷容器dbdata,并在其中创建一个数据卷挂载到/dbdata:

1
2
$ docker run -it -v /dbdata --name dbdata centos
root@3ed94f279b6f:/#

2.查看/dbdata目录:

1
2
3
root@3ed94f279b6f:/# ls

bin boot **dbdata** dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var

3.在其他容器中使用–volumes-from来挂载dbdata容器中的数据卷.

例如创建db1和db2两个容器,并从dbdata容器挂载数据卷:

1
2
3
$ docker run -it --volumes-from dbdata --name db1 ubuntu

$ docker run -it --volumes-from dbdata --name db2 ubuntu

此时,容器db1和db2都挂载同一个数据卷到相同的/dbdata目录。三个容器任何一方在该目录下的写入,其他容器都可以看到。

例如,在dbdata容器中创建一个test文件,如下所示:

1
2
3
4
5
6
7
root@3ed94f279b6f:/# cd /dbdata

root@3ed94f279b6f:/dbdata# touch test

root@3ed94f279b6f:/dbdata# ls

test

在db1容器内查看它:

1
2
3
4
5
6
7
$ docker run -it --volumes-from dbdata --name db1  ubuntu

root@4128d2d804b4:/# ls
bin boot dbdata dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var

root@4128d2d804b4:/# ls dbdata/
test

4.数据卷的生命周期一直会持续到没有容器使用他时

六、Dockerfile

Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。

1、Dockerfile基础知识:

1)每条保留字指令都必须是大写字母且后面要跟随至少一个参数

2)指令从上到下顺序执行

3)#表示注释

4)==每条指令都会创建一个新的镜像层,并对镜像进行提交==

2、Docker执行Dockerfile的流程

1)Docker从基础镜像运行一个容器

2)执行一条指令就对容器进行修改

3)执行完一条指令就使用类似docker commit的操作提交一个新的==镜像层==

4)docker再基于刚刚提交的==镜像==运行一个新容器

  • 由于镜像是由多个镜像层组成的,所以提交一个镜像层 <==> 生成了一个新镜像

5)继续执行下一条指令,直到所有指令都执行完毕

从应用软件的角度上来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段

  • Dockerfile:软件原材料,面向开发
    • Docker镜像:软件的交付品
    • Docker容器:软件运行状态

3、Dockerfile的保留字指令

1)FROM

基础镜像,当前镜像是基于哪个镜像的

2)MAINTAINER

镜像维护者的姓名和邮箱地址

3)RUN

容器构建时需要运行的命令

4)EXPOSE

容器对外暴露的端口

5)WORKDIR

指定创建容器后,终端默认登陆进来的工作目录

6)ENV

在构建镜像过程中设置环境变量

eg:

1
2
3
4
# 声明一个环境变量,这个变量可以在后续的任何指令中使用
ENV MY_PATH /usr/test
# 比如设置工作目录
WORKDIR $MY_PATH

7)ADD

将宿主机目录下的文件copy进镜像,而且ADD命令会自动处理URL和解压压缩包

8)COPY

将文件copy到镜像中

9)VOLUME

容器数据卷,用于数据的保存和持久化工作

10)CMD

指定容器启动时要运行的命令

  • Dockerfile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数==替换==
    • 类似docker run /bin/sh xxx这种

11)ENTRYPOINT

指定容器启动时要运行的命令

  • ENTRYPOINT会==追加==docker run之后的参数

12)ONBUILD

当构建一个被继承的Dockerfile时运行的命令,父镜像在被子镜像继承后触发这个命令

七、将镜像发布到阿里云上

1.创建镜像仓库

2.将镜像推送到阿里云上

1
2
3
4
$ sudo docker login --username=1203901753@qq.com registry.cn-hangzhou.aliyuncs.com
# 本地镜像id 想要在阿里云上显示的版本号
$ sudo docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/x5456/centos:[镜像版本号]
$ sudo docker push registry.cn-hangzhou.aliyuncs.com/x5456/centos:[镜像版本号]

3.在阿里云上查看

CATALOG
  1. 1. 一、Docker简介
  2. 2. 二、Docker的安装
    1. 2.1. 1、安装Docker
    2. 2.2. 2、配置阿里云镜像加速
    3. 2.3. 3、hello,world
    4. 2.4. 4、Docker是怎么工作的
    5. 2.5. 5、Docker为什么比虚拟机快
  3. 3. 三、常用命令
    1. 3.1. 1、帮助命令
    2. 3.2. 2、镜像命令
      1. 3.2.1. 1)查看本地主机中的所有镜像
      2. 3.2.2. 2)从hub上查找镜像
      3. 3.2.3. 3)下载镜像
      4. 3.2.4. 4)删除镜像
    3. 3.3. 3、容器命令
      1. 3.3.1. 1)新建并启动容器
      2. 3.3.2. 2)列出Docker中有哪些容器在运行
      3. 3.3.3. 3)退出交互式容器
      4. 3.3.4. 4)其他操作
      5. 3.3.5. 5)守护式启动
      6. 3.3.6. 6)查看容器日志
      7. 3.3.7. 7)查看容器内部细节
      8. 3.3.8. 8)进入正在运行的容器并以命令行交互
      9. 3.3.9. 9)拷贝容器中的文件到本地
    4. 3.4. 四、Docker镜像
      1. 3.4.1. 1、UnionFS联合文件系统
        1. 3.4.1.1. 为啥tomcat会辣么大??
        2. 3.4.1.2. 采用这种分层结构的好处
      2. 3.4.2. 2、生成镜像Demo
    5. 3.5. 五、Docker的数据管理
      1. 3.5.1. 1、数据卷
        1. 3.5.1.1. 1)使用命令添加
        2. 3.5.1.2. 2)采用DockerFile进行添加
      2. 3.5.2. 2、数据卷容器
    6. 3.6. 六、Dockerfile
      1. 3.6.1. 1、Dockerfile基础知识:
      2. 3.6.2. 2、Docker执行Dockerfile的流程
      3. 3.6.3. 3、Dockerfile的保留字指令
        1. 3.6.3.1. 1)FROM
        2. 3.6.3.2. 2)MAINTAINER
        3. 3.6.3.3. 3)RUN
        4. 3.6.3.4. 4)EXPOSE
        5. 3.6.3.5. 5)WORKDIR
        6. 3.6.3.6. 6)ENV
        7. 3.6.3.7. 7)ADD
        8. 3.6.3.8. 8)COPY
        9. 3.6.3.9. 9)VOLUME
        10. 3.6.3.10. 10)CMD
        11. 3.6.3.11. 11)ENTRYPOINT
        12. 3.6.3.12. 12)ONBUILD
    7. 3.7. 七、将镜像发布到阿里云上