日志:179 评论:30
北京, 西城
【Docker】Docker学习笔记

Docker是一个容器软件

概念

容器就相当于VMware,是一个虚拟环境。

安装

我们这里以CentOS 7为例

使用yum安装docker

yum -y install docker

验证

输入命令

docker -v

启动

关闭SELinux,这玩意和docker合不来

打开selinux的配置文件

vi /etc/sysconfig/selinux

修改文件内容

SELINUX=enforcing # 找到这一行修改为 SELINUX=disabled

重启服务器

reboot

重启docker

systemctl restart docker

自动启动

systemctl enable docker

Docker创建私有仓库(repository)

第一步

拉一个registry镜像下来

docker pull registry

第二步

运行仓库

docker run -d -p 5000:5000 -v /opt/registry:/tmp/registry docker.io/registry

第三步

验证

docker ps -a

查看镜像

V1版本是

curl 127.0.0.1:5000/v1/search

V2版本是

curl 127.0.0.1:5000/v2/_catalog

创建镜像

第一步

先拉一个镜像从远程仓库

docker pull centos

第二步

修改tag到本地

docker tag docker.io/centos 127.0.0.1:5000/centos:tongfu

第三步

上传镜像到本地仓库

docker push 127.0.0.1:5000/centos:tongfu

Docker容器操作(container)

创建容器

docker run -tid --name [容器名称] [镜像名称]

进入容器

采用attach进入容器后,通过exit退出的话,容器会停止运行

docker attach [容器名称]

在容器内执行命令

docker exec [容器名称] /bin/bash -c "命令"

停止容器

docker stop [容器名称]

启动容器

docker start [容器名称]

退出容器

正常进入容器后退出的话,容器会停止运行,那么如何保证退出后容器一直运行呢?

答案是通过 exec 进入容器,命令如下:

docker exec -ti [容器名称] /bin/bash

这样也可以进入容器,同时这样退出不会导致容器停止运行

删除容器

要删除一个容器之前必须要先停止这个容器

docker rm [容器名称]

Docker网络配置(network)

创建网络

注意:虚拟网络的IP网段千万不要和本地物理网络冲突,否则会导致容器内部网络不通的情况!!!

docker network create --subnet=10.16.1.0/16 --gateway=10.16.1.1 --opt "com.docker.network.bridge.name"="bridge2" bridge2

使用新网络创建容器

docker run -tid --name=base --net=bridge2 --ip=10.16.1.100 -p 8000:80 docker.tongfu.net:5000/centos

这样新创建的容器的IP地址就是bridge2网络的地址,通过网关IP可以与宿主机互相通讯,同时我们将容器的80端口映射给了宿主机8000端口。

容器IP地址:10.16.1.100

宿主机IP地址:10.16.1.1

容器端口:80

宿主机端口:8000

查看网络列表

[root@tongfunet]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
2f03bb8a8a13        bridge              bridge              local
3919c34c3c33        bridge2             bridge              local
305e882739a3        host                host                local
363c4d747119        none                null                local

删除网络

注意默认的几个网络不要动(bridge、host、none)

[root@tongfunet]# docker network rm bridge2
bridge2

查看网络列表

[root@tongfunet]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
2f03bb8a8a13        bridge              bridge              local
305e882739a3        host                host                local
363c4d747119        none                null                local

Docker导出与导入(export/import)

导出

将容器内容导出到一个压缩包内

[root@tongfunet]# docker export [容器名称] > [压缩包名称].tar

导入

从一个压缩包内导入数据到镜像里

[root@tongfunet]# docker import [压缩包名称].tar [镜像名称]

另一种导入命令

[root@tongfunet]# cat [压缩包名称].tar | docker import - [镜像名称]

Docker容器生成镜像(image)

提交到仓库

我们辛辛苦苦调试好的容器,不想一个不小心就丢了,还想给其他人用,怎么办?

我们可以通过comment命令将自己的容器提交到仓库

base是现有容器名称

base-net是新的镜像名称

docker commit -m "m" -a "a" base docker.tongfu.net:5000/centos:base-net

查看镜像列表

看我们的容器变成了镜像,可以通过run使用了

# docker images

REPOSITORY                      TAG                 IMAGE ID            CREATED             SIZE
docker.tongfu.net:5000/centos   base-net            e026052245dc        44 seconds ago      303.7 MB

删除镜像

删除一个镜像必须要删除所有基于这个镜像创建的容器

docker rmi [镜像id]

查看镜像

我们可以查看镜像信息,包括创建参数,依赖镜像等等

# docker history [镜像id]

IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
ec7d21826858        12 months ago       /usr/sbin/init                                  56.69 MB            Web server 2.4.27 for CentOS 7
b6bac0adfc18        12 months ago       /usr/sbin/init                                  141.7 MB            The pure CentOS with net-tools , crontabs , gcc , make
ff426288ea90        12 months ago       /bin/sh -c #(nop)  CMD ["/bin/bash"]            0 B                 
<missing>           12 months ago       /bin/sh -c #(nop)  LABEL name=CentOS Base Ima   0 B                 
<missing>           12 months ago       /bin/sh -c #(nop) ADD file:6bba01fe946852a560   207.2 MB

Docker备份与还原(backup/restore)

备份

我们要将做好的镜像备份起来,可以使用下面的命令

docker save docker.tongfu.net:5000/centos:base -o /tongfu.net/docker/backup/base.tgz

还原

我们要使用备份的文件还原,可以使用下面的命令

docker load -i /tongfu.net/docker/backup/base.tgz

Docker导出与导入

导出

我们要将做好的容器用在其他地方,可以使用下面的命令导出到一个压缩文件

导入

我们要将导出的压缩文件在其他地方还原到容器里,可以使用下面的命令

Docker数据目录迁移(move data directory)

迁移数据目录

停止服务

systemctl stop docker

移动数据目录

mv /var/lib/docker /data/docker

建立符号链接

ln -s /data/docker /var/lib/docker

启动服务

systemctl start docker

Docker常见问题

save/load和export/import区别

  • save/load生成的镜像包含容器的依赖镜像的每一层信息,容量比较大。

  • export/import生成的镜像没有历史镜像信息,无法进行回滚操作,相对容量比较小。

Docker的存储驱动(Storage Driver)

介绍

docker有这么几种存储驱动,OverlayFS(overlay),AUFS(aufs),Btrfs(btrfs),Device Maper(devicemapper),VFS*(vfs),ZFS(zfs)

其中旧版本默认采用的驱动是devicemapper,最新版本1.13.x默认采用的驱动是overlay2

区别

overlay

这里面根据笔者的经验,我们只谈谈overlay这种驱动。

在使用最新版本1.13.x进行镜像设计的过程中发现了一个bug,就是通过images开启的容器内部,如果要删除镜像自带目录会被告知:Directory not emtpy。

很迷惑的一个提示。。

笔者一开始以为是被进程占用了,各种查找,各种重启容器,重启docker,各种reboot,各种重建容器,依然解决不了问题。

但是映射进来的目录就完全正常!

最后发现这是overlay的一大特性,出于对镜像模板内容的保护,删除操作会被禁止,用户内容需要通过映射目录方式实现。

好吧~~这是好事,习惯了就好~~

那个不知所谓的 Directory not empty 是迷糊“黑客”的。。

devicemapper

这种方式下,我们操作容器内的内容没有任何限制

网上一些文章倡导用这种驱动替代overlay驱动,解决不能rm -rf的问题

我个人的主张,没有必要,要学会接受新鲜事物~~

当然,学习如何切换存储驱动到是可以的!

常见错误

建立容器

容器无法联网

创建容器的时候,报如下警告信息

WARNING: IPv4 forwarding is disabled. Networking will not work.

解决方法

echo "net.ipv4.ip_forward=1" >> /usr/lib/sysctl.d/00-system.conf

systemctl restart network
systemctl restart docker

YUM

使用yum报错

使用yum报错rpmdb open failed信息

error: rpmdb: BDB0004 fop_read_meta: /var/lib/rpm/Packages: unexpected file type or format
error: cannot open Packages index using db5 - Invalid argument (22)
error: cannot open Packages database in /var/lib/rpm
CRITICAL:yum.main:

Error: rpmdb open failed

解决方法

rm -f /var/lib/rpm/*
rpm --rebuilddb
yum clean all