docker基础

 

一、docker简介

1、docker简介


容器( container-based )虚拟化方案,充分利用了操作系统本身已有的机制和特性,以实现轻量级的虚拟化(每个虚拟机安装的不是完整的虚拟机), 甚至有人把他称为新一代的虚拟化技术, Docker 无疑就是其中的佼佼者
在一台服务器上同时运行上百个虚拟机,肯定会被认为是痴人说梦,而在一台机器上同时运 行一千个 Docker 容器,这已成为现实


2、Docker 的目标


Build,Ship and Run Any App,Anywhere— 即通过对 应用组件的封装 (Packaging), 发布(Distribution), 运行 (runing) 等生命周期的管理 , 达到应用组件级别的”一 次封装 , 到处运行

3、docker的特点

优点:

启动快,资源占用小 , 资源利用高,快速构建标准化运行环境
创建分布式应用程序时快速交付和部署,更轻松的迁移和扩展,更简单的更新管理


局限:
Docker 是基于 Linux 64bit 的,无法在 windows/unix 或 32bit 的 linux环境下使用 
LXC 是基于 cgroup 等 linux kernel 功能的,因此 container 的 guest 系统只能是 linux 
隔离性相比 KVM 之类的虚拟化方案还是有些欠缺,所有 container 公用一部分的运行库 
管理相对简单,主要是基于 namespace 隔离 
cgroup 的 cpu 和 cpuset 提供的 cpu 功能相比 KVM 的等虚拟化方案相比难以度量 ( 所以 dotcloud 主要是按内存收费 ) l
docker 对 disk 的管理比较有限 
container 随着用户进程的停止而销毁, container 中的 log 等用户数据不便收集

 

4、docker与虚拟机的比较


启动快比虚拟机 , 可以秒级启动
资源占用小 , 宿主机上可运行千台容器
方便用户获取 , 分布 , 和更新应用镜像 , 指令简单 , 学习费用低
通过 Dockerfile 配置文件来灵活的自动创建和部署镜像 & 容器 , 提高工作效 率
Docker 除了运行其中应用外 , 基本不消耗其他系统资源 , 保证应用性能同时 , 尽量减小系统开销

5、docker重要网站
https://hub.docker.com/
https://docs.docker.com/
http://docs.docker-cn.com/

二、docker的安装


方案一:网络源
wget  http://download2.yunwei.edu/shell/docker.tar.gz(推荐)

tar xf docker.tar.gz && cd docker && bash docker.sh

方案二:yum安装
yum -y install docker

下载后:systectl restart docker 重启

 


三、docker镜像

镜像(docker image) --- Docker 运行容器之前需要本地存在镜像,若本 能地不存在,那么 Docker 会找默认镜像仓库( Docker Hub 公共注册服务 器中的仓科)下载,用户也可以通过配置使用自己的镜像库

(1)下载镜像 docker pull name:tag 

eg: docker pull ubuntu:latest 若在下载时你未指定标签,默认追加 latest标签,表示库中最新镜像
镜像在下载过程中是分层的,并且在每层前会有各层的 ID号,层(Layer ) 是 AUFS (联合文件系统)的重要概念,是实现增量保存与更新的基础

root@localhost ~]# docker pull registry
Using default tag: latest
latest: Pulling from library/registry
c87736221ed0: Downloading  2.028MB/2.207MB
1cc8e0bb44df: Download complete 
54d33bcb37f5: Download complete 
e8afc091c171: Download complete 
b4541f6d3db6: Download complete 

可以看到registry得下载分成了5层。


(2)查看本地镜像相关信息 docker images

显示结果:

 

四、docker的镜像分层

docker镜像的分层结构:支持通过扩展现有镜像,创建新的镜像

可以看到,新镜像是从 base 镜像一层一层叠加生成的每安装一个软件,就 在现有镜像的基础上增加一层。

分层结构的优势:

共享资源:
多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘 上保存一份 base 镜像;同时内存中也只需加载一份 base 镜像,就可以为所 有容器服务了。而且镜像的每一层都可以被共享,我们将在后面更深入地讨论 这个特性。


这时可能就有人会问了:如果多个容器共享一份基础镜像,当某个容器修改了 基础镜像的内容,比如 /etc 下的文件,这时其他容器的 /etc 是否也会被修改?
答案是不会! 修改会被限制在单个容器内。 这就是我们接下来要学习的容器 Copy-on-Write 特性。


可写的容器层:

当容器启动时,一个新的可写层被 加载到镜像的顶部。这一层通常被 称作“容器层”,“容器层”之下 的都叫“镜像层”。
所有对容器的改动 - 无论添加、删除、还是修改文件都只会发生在容器层中
只有容器层是可写的,容器层下面的所有镜像层都是只读的。

镜像层数量可能会很多,所有镜像层会联合在一起组成一个统一的文件系统。 如果不同层中有一个相同路径的文件,比如 /a,上层的 /a 会覆盖下层的 /a, 也就是说用户只能访问到上层中的文件 /a。在容器层中,用户看到的是一个叠 加之后的文件系统。

添加文件
在容器中创建文件时,新文件被添加到容器层中
读取文件
在容器中读取某个文件时,Docker 会从上往下依次在各镜像层中查找此文 件。一旦找到,打开并读入内存

修改文件
在容器中修改已存在的文件时,Docker 会从上往下依次在各镜像层中查找 此文件。一旦找到,立即将其复制到容器层,然后修改之。
删除文件
在容器中删除文件时,Docker 也是从上往下依次在镜像层中查找此文件。 找到后,会在容器层中记录下此删除操作。


有当需要修改时才复制一份数据,这种特性被称作 Copy-on-Write。可见, 容器层保存的是镜像变化的部分,不会对镜像本身进行任何修改。

这样就解释了我们前面提出的问题:容器层记录对镜像的修改,所有镜像层都 是只读的,不会被容器修改,所以镜像可以被多个容器共享。

五、docker镜像创建

创建镜像的三种方法


(1)基于修改后的容器创建:docker commit 命令
(2)基于本地模板导入
(3)基于 Dockerfile 文件创建

(1)基于修改后的容器创建

进入容易后创建一个目录(也就是发生了修改)

[root@localhost docker]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello               latest              48610725cfd0        2 hours ago         109MB
nnginx              latest              b2bdaac40f58        3 hours ago         109MB
registry            latest              f32a97de94e1        3 months ago        25.8MB
[root@localhost docker]# docker run -it nnginx:latest /bin/bash
root@aab5b75378d0:/# mkdir /testdir
root@aab5b75378d0:/# exit


此时容器较镜像已经发生改变,我们以此生成新镜像
docker commit container-name(容器名) image-name(镜像名)

[root@localhost docker]# docker commit  aab5b75378d0 nnginx:latest
sha256:5b256a080fe8b01098ca978df98fcdba6456a066e5f84e025e3622b5c3604c6a
[root@localhost docker]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nnginx              latest              5b256a080fe8        10 seconds ago      109MB
hello               latest              48610725cfd0        2 hours ago         109MB
registry            latest              f32a97de94e1        3 months ago        25.8MB

可以看到id发生了改变,新镜像生成。

如果需要复制并重命名,执行

 docker tag nnginx:latest (旧名) nginx:latest(新名)

重命名后的id相同

(2)基于模板导出和导入镜像
导出:将镜像保存为本地文件

1.  docker save -o nginx.tar(压缩包)  nginx:latest(镜像名)

[root@localhost docker]# docker save -o nginx.tar nginx:latest

2.然后我执行删除本地镜像

[root@localhost docker]# docker rmi nginx:latest(镜像名或者id都可以)
Untagged: nginx:latest
Deleted: sha256:5b256a080fe8b01098ca978df98fcdba6456a066e5f84e025e3622b5c3604c6a
Deleted: sha256:ba4206ee789b80bd1a1bcc9bf86b62becbd607f6244e14d6df3652df937c4b1c

3.将压缩包导入

可以看到删除的nginx镜像被恢复了过来,并且id没有改变。

简单来说,容器是镜像的运行实体。所不同的是它带有额外的可写层

(3)基于 Dockerfile 文件创建

Dockerfile 是一个文本文件,用来配置 image,记录了镜像构建的所有步骤。
Docker 根据 该文件生成二进制的 image 文件。

如何可以生成 image 文件? 如果你要推广自己的软件,势必要自己制作 image 文件。
下面通过一个实例,演示如何编写 Dockerfile 文件:

1、创建dockerfile的目录并cd进入创建dockerfile的文件。

2、写下拉取的镜像和要执行的命令

3、使用“ docker build -t 镜像名 路径 ”的命令来创建镜像

4、查看

[root@localhost ~]# cd dockerfile/
[root@localhost dockerfile]# cat dockerfile 
FROM nginx:latest
RUN touch mama
[root@localhost dockerfile]# docker build -t new-nginx:latest .    # 指明 build context 为当前目录,我们也可以通过 -f 参数指定 Dockerfile 的位置
Sending build context to Docker daemon  13.31kB              #-t 指定新镜像名字
Step 1/2 : FROM nginx:latest
 ---> 5b256a080fe8
Step 2/2 : RUN touch mama
 ---> Running in 49e9328bfb39
Removing intermediate container 49e9328bfb39
 ---> 4127cc59bca1
Successfully built 4127cc59bca1
Successfully tagged new-nginx:latest
[root@localhost dockerfile]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
new-nginx           latest              4127cc59bca1        47 seconds ago      109MB
nginx               latest              5b256a080fe8        33 minutes ago      109MB
hello               latest              48610725cfd0        3 hours ago         109MB
registry            latest              f32a97de94e1        3 months ago        25.8MB

从这步开始就是镜像真正的构建过程。 首先 Docker 将 build context 中的所有 文件发送给 Docker daemon。build context 为镜像构建提供所需要的文件或 目录。Dockerfile 中的 ADD、COPY 等 命令可以将 build context 中的文件添加 到镜像。此例中,build context 为当前 目录 /root/docker,该目录下的所有文件 和子目录都会被发送给 Docker daemon。 所以,使用 build context 就得小心 了,不要将多余文件放到 build context, 特别不要把 /、/usr 作为 build context, 否则构建过程会相当缓慢甚至失败。

Docker 会缓存已有镜像的镜像层,构建新镜像时,如果某镜像层已经存在,就 直接使用,无需重新创建。在前面的 Dockerfile 中添加一点新内容,往镜像中复制 一个文件:

下面列出了 Dockerfile 中最常用的指令,完整列表和说明可参看官方文档。
FROM:指定 base 镜像。

MAINTAINER:设置镜像的作者,可以是任意字符串。

COPY:将文件从 build context 复制到镜像。
COPY 支持两种形式:
COPY src dest
COPY ["src", "dest"] 注意:src 只能指定 build context 中的文件或目录。

ADD:与 COPY 类似,从 build context 复制文件到镜像。不同的是,如果 src 是归档文件(tar, zip, tgz, xz 等),文件会 被自动解压到 dest

ENV:设置环境变量,环境变量可被后面的指令使用。例如:
...
ENV MY_VERSION 1.3
RUN apt-get install -y mypackage=$MY_VERSION
...

EXPOSE:指定容器中的进程会监听某个端口Docker 可以将该端口暴露出来。我们会在容器网络部分详细讨论。

VOLUME:将文件或目录声明为 volume。

WORKDIR:为后面的 RUN, CMD, ENTRYPOINT, ADD 或 COPY 指令设置镜像中的当前工作目录。

RUN:在容器中运行指定的命令RUN 指令通常用于安装应用和软件包。

CMD:容器启动时运行指定的命令。 Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效。CMD 可以被 docker run 之后的参数替换。

ENTRYPOINT:设置容器启动时运行的命令,可让容器以应用程序或者服务的形式运行。
Dockerfile 中可以有多个 ENTRYPOINT 指令,但只有最后一个生效。CMD 或 docker run 之后的参数会被当做参数传递给 ENTRYPOINT。

完整的dockerfile创建镜像过程:


 1)将hello world文件压缩,另外创建一个file文件
[root@localhost dockerfile]# touch hello
[root@localhost dockerfile]# vim dockerfile 
[root@localhost dockerfile]# touch world
[root@localhost dockerfile]# tar cvf test.tar hello world
hello
world
[root@localhost dockerfile]# ls
dockerfile  hello  test.tar  world
[root@localhost dockerfile]# rm -rf hello world
[root@localhost dockerfile]# ls
dockerfile  test.tar
[root@localhost dockerfile]# touch file
[root@localhost dockerfile]# ls
dockerfile  file  test.tar


2)在dockerfile文件里添加如下命令 [root@localhost dockerfile]# cat dockerfile FROM nginx:latest MAINTAINER sb WORKDIR
/testdir RUN touch mama COPY file .          这里的.是目标路径,也就是工作目录的当前路径。当然我们也可以自己指定路径。 ADD test.tar . ENV WLECOME "welcome to my container"

以上创建复制的文件都会在镜像的工作目录testdir下。
[root@localhost dockerfile]# docker build -t hello . Sending build context to Docker daemon 13.31kB Step 1/7 : FROM nginx:latest ---> 5b256a080fe8 Step 2/7 : MAINTAINER sb ---> Using cache ---> 3eded0b4433a Step 3/7 : WORKDIR /testdir ---> Using cache ---> b2aff1ca7d85 Step 4/7 : RUN touch mama ---> Using cache ---> 6884f574c04a Step 5/7 : COPY file . ---> 64be2597f918 Step 6/7 : ADD test.tar . ---> 1fba4d3cffef Step 7/7 : ENV WLECOME "welcome to my container" ---> Running in 8ffedf2c1ec5 Removing intermediate container 8ffedf2c1ec5 ---> b7101fae716a Successfully built b7101fae716a Successfully tagged hello:latest


执行完创建命令后查看。 [root@localhost dockerfile]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello latest b7101fae716a
10 seconds ago 109MB new-nginx latest 4127cc59bca1 23 minutes ago 109MB nginx latest 5b256a080fe8 About an hour ago 109MB registry latest f32a97de94e1 3 months ago 25.8MB [root@localhost dockerfile]# ls dockerfile file test.tar [root@localhost dockerfile]# docker run -it hello:latest /bin/bash root@5a20c55fad40:/testdir# ls file hello mama world

六、docker使用

(1)创建容器,create命令是创建并不启动容器
docker create -it nginx

(2)查看所有状态的容器
docker ps -a 

(3)启动停止的容器
docker start 容器ID

(4)运行一个容器
docker run -ti nginx:latest  /bin/bash

创建并运行一个容器 ,此时你会直接被切换到容器中
#ctrl+d//exit退出,并且容器也退出
#ctrl+p+q退出容器,并且保持容器up的状态


-t 分配一个伪终端
-i 让容器的标准输入持续打开
用/bin/bash环境显示 docker的使用 

(5)以后台守护进程(Daemonized)形态运行
用-d参数实现
docker run -dti docker.io/centos:7

(6)终止容器
docker stop NAME/ID 或者 docker kill NAME/ID

(7)重启容器
docker restart NAME/ID

需要注意,非持久后台守护状态的虚拟机,在重启后当你查看时还是关闭状态

(8)删除容器
语法: docker rm (参数)  容器名
#docker -rm -f NAME/ID
-f 强制删除处于运行中的容器
-l 删除链接,保留容器
-v 删除挂载的数据卷


(9)进入容器
docker attachdocker exec 两种方式:

docker attach

直接进入容器 启动命令的终端,不会启动新的进程

docker run -d centos /bin/bash -c “while true; do sleep 1;echo I_am_docker;done”

docker attach 容器名


docker exec则是在容器中打开新的终端,并且可以启动新的进程 
docker exec -it 容器名  /bin/bash

root@localhost dockerfile]# docker run -d hello /bin/bash -c "while true;do sleep 1;echo I_am_docker;done"
431cc4bc8cf6b34b7b8fc937c864cf46ad22508de7a34339a8c507103d1b343c
[root@localhost dockerfile]# docker attach 431cc4bc8cf6      
I_am_docker
I_am_docker
I_am_docker
I_am_docker
。。。
[root@localhost dockerfile]# docker exec
-it 431cc4bc8cf6 /bin/bash root@431cc4bc8cf6:/#

(10)导入和导出容器
a. 导出容器:导出一个已经创建的容器到文件,不管容器是否运行

假设当前系统中有两个处于运行和停止状态的容器
docker export ID > *.tar      #以压缩包格式导出

[root@localhost dockerfile]# docker export 431cc4bc8cf6  > hello.tar
[root@localhost dockerfile]# ls
dockerfile  file  hello.tar

b.将容器导入系统成为镜像 
cat *.tar | docker import - test

[root@localhost dockerfile]# cat hello.tar | docker import - hello    # - 指定镜像名
sha256:e78e43cdf98d31641172d0eed9083dea9cb6d47a1c5237e41748e7b16d9b8f62

 

c.docker images查看

[root@localhost dockerfile]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello               latest              e78e43cdf98d        23 seconds ago      108MB
<none>              <none>              b7101fae716a        About an hour ago   109MB
new-nginx           latest              4127cc59bca1        About an hour ago   109MB

可以看到之前hello命令的镜像文件名字被替代,变成了<none>,但是依然能够运行。

(11)查看容器日志
显示容器启动进程的控制台输出
docker logs -f 容器名

(12)暂停容器
docker pause NAME/ID

(13)取消暂停继续运行容器
docker unpause NAME/ID

 

七、docker镜像的仓库

--- repository的创建:
仓库分为公共仓库和私有仓库
DockerHub的官方仓库 https://hub.docker.com
DockerPool社区仓库 https://dl.dockerpool.com
Dockern Pool (http://dockerpool.com)是国内专业的Docker社区,目前 也提供了官方镜像的下载管理服务


仓库 --- 创建自己的私有仓库

 (1) 下载本地仓库registry:docker pull registry
 ( 2) docker run -d -p 5000:5000 -v /var/lib/registry:/var/lib/registry --restart=always --name registry
registry:latest


(3)docker客户端设置,
2.1. 修改配置文件将私有库地址加入进去
vim /etc/sysconfig/docker
line 4: add Docker-Registry's URL
OPTIONS='--insecure-registry 192.168.210.128:5000 --selinux-enabled --log-driver=journald.....'

(3)systemctl restart docker 重新启动 docker服务
(4)docker tag my-imge:latest 192.168.210.128:5000/myimge1:latest 更换 my-imge:latest 一个新的名称标签
(5)docker push 192.168.210.128:5000/my-imge1:latest
上传 my-imge1:latest
(6)删除本地原有的busybox 镜像,然后向私有库192.168.254.162重新下载
docker rmi 192.168.210.128:5000/my-imge1:latest
docker pull 192.168.210.128:5000/my-imge1:latest

 或者第二种方案:

从第(3)步开始:

cd 到/etc/docker

然后在配置文件daemon.json第二行添加下面绿色的命令,端口号5000,ip为docker服务端ip。

[root@dlp dockerfile]# cd /etc/docker/
[root@dlp docker]# cat daemon.json 
{
  "registry-mirrors": ["http://cc83932c.m.daocloud.io"],
  "insecure-registries": ["192.168.253.9:5000"],
"max-concurrent-downloads": 10, "log-driver": "json-file", "log-level": "warn", "log-opts": { "max-size": "10m", "max-file": "3" } }

4)更改镜像名

[root@dlp docker]# docker tag httpd:latest 192.168.253.9:5000/httpd:latest
[root@dlp docker]# docker images
REPOSITORY                 TAG                 IMAGE ID            CREATED             SIZE
192.168.253.9:5000/httpd   latest              e77c77f17b46        6 days ago          140MB
httpd                      latest              e77c77f17b46        6 days ago          140M

5)上传镜像

  docker push 镜像名:tag

[root@dlp docker]# docker push 192.168.253.9:5000/httpd:latest
The push refers to repository [192.168.253.9:5000/httpd]
6c4a74a82dc9: Pushed 
9cba8b480e83: Pushed 
25797e1a8e3f: Pushed 
d2583584487e: Pushed 
cf5b3c6798f7: Pushed 
latest: digest: sha256:f97d825efe5c69fbe031222292571af05a2b5cdc767e7190e93d7dab3367a9a1 size: 1367

 如果报错:

一、Get http://192.168.253.9:5000/v2/: dial tcp 192.168.253.9:5000: getsockopt: connection refused

原因:1)镜像名更改格式错误,必须把端口号加上。

   2)添加的配置内容ip错误。

二、Get https://192.168.253.9/v2/: dial tcp 192.168.253.9:443: getsockopt: no route to host

原因:防火墙没关闭

6)删除所有的镜像,从服务节点的仓库中下载

  docker pull 镜像名:tag

[root@dlp docker]# docker pull 192.168.253.9:5000/httpd:latest
latest: Pulling from httpd
fc7181108d40: Pull complete 
b183a5e3b6da: Pull complete 
c52952f0d826: Pull complete 
c8f255a56e9a: Pull complete 
144c3b858b48: Pull complete 
Digest: sha256:f97d825efe5c69fbe031222292571af05a2b5cdc767e7190e93d7dab3367a9a1
Status: Downloaded newer image for 192.168.253.9:5000/httpd:latest
原文地址:https://www.cnblogs.com/zzzynx/p/11041592.html