Docker


Docker属于Linux容器的一种封装,提供简单易用的容器使用接口。它是目前最流行的Linux容器解决方案。Docker将应用程序与该程序的依赖,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器。程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样。有了Docker,就不用担心环境问题。

开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。

Docker 与虚拟机的区别

虚拟机是一个运行在宿主机之上的完整的操作系统,它主要是通过Hypervisor对硬件资源进行虚拟化。

Docker不同于虚拟机,Docker是对软件和其依赖的标准化打包,基于container运行在宿主机上,实现应用之间的隔离,应用之间是共享一个OS kernel。

vm_container.png

Dcoker 相关概念

Docker是基于CS架构的:

Docker daemon: 运行在宿主机上,Docker守护进程,用户通过Docker client(Docker命令)与Docker daemon交互。

Docker client: Docker 命令行工具,是用户使用Docker的主要方式,Docker client与Docker daemon通信并将结果返回给用户,Docker client也可以通过socket或者RESTful api访问远程的Docker daemon。

Docker image: 镜像是只读的,镜像中包含有需要运行的文件。镜像用来创建container,一个镜像可以运行多个container。镜像可以通过Dockerfile创建,也可以从Docker hub/registry下载。

Docker container: 容器是Docker的运行组件,启动一个镜像就是一个容器,容器是一个隔离环境,多个容器之间不会相互影响,保证容器中的程序运行在一个相对安全的环境中。

Docker hub/registry: 共享和管理Docker镜像,用户可以上传或者下载上面的镜像,类似于github。官方地址为https://registry.hub.docker.com/,也可以搭建自己私有的Docker registry。

安装 Dcoker

由于在国内使用官方的镜像仓库安装,会比较慢。在国内可以通过阿里云的镜像仓库安装docker:

curl -sSL http://acs-public-mirror.oss-cn-hangzhou.aliyuncs.com/docker-engine/internet | sh -

为了避免每次使用docker,都需要用sudo命令,可以把当前用户添加到docker的用户组中,最后重启SHELL即可:

sudo groupadd docker
sudo usermod -aG docker $USER
sudo service docker restart

安装完成后,可以使用下面的命令,查看docker是否安装成功:

docker version

Dcoker 的基本使用

拉取镜像

运行下面的命令,如果在本地没有相关的镜像,docker会从docker hub上拉取相应的镜像。

[heql@ubuntu ~]$ docker pull hello-world
Using default tag: latest
latest: Pulling from library/hello-world
d1725b59e92d: Pull complete 
Digest: sha256:0add3ace90ecb4adbf7777e9aacf18357296e799f81cabc9fde470971e499788
Status: Downloaded newer image for hello-world:latest

docker默认拉取的是最新的镜像,如果想要拉取指定版本的镜像(可以在docker hub查看所有的版本),如下命令,是拉取ubuntu:14.04的镜像:

[heql@ubuntu ~]$ docker pull ubuntu:14.04

查看镜像

运行下面的命令可以查看本机的docker image:

[heql@ubuntu ~]$ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              14.04               f216cfb59484        2 
hello-world         latest              4ab4c602aa5e        2 months ago        1.84kB

或者使用:

[heql@ubuntu ~]$ docker images

删除镜像

[heql@ubuntu ~]$ docker rmi f216cfb59484
Untagged: ubuntu:14.04
Untagged: ubuntu@sha256:e6e808ab8c62f1d9181817aea804ae4ba0897b8bd3661d36dbc329b5851b5637
Deleted: sha256:f216cfb594848488b1b885dfb5da441ea828555471c1886c0512bdb02ecdf644
Deleted: sha256:5d97e3b2bf5251541b6e8dee661ee0bed7850b558fcdfc442dfd438d1e502e6e
Deleted: sha256:b41f04d087b0b3a3a7e2fbf69e2272683eff4527ca8a6e2bb8f09b4bd2a74194
Deleted: sha256:8e7e33e062f998816b21527bf79c630f956d7241107818d1d4f47491be8367c9
Deleted: sha256:adb1f7ffb432495d0345c5d1fdb165d0346735210c71fb3e52ca7f79dffe9c23

或者可以使用:docker rm image f216cfb59484

运行容器

[heql@ubuntu ~]$ docker run hello-world

Hello from Docker!

查看容器

使用下面的命令,可以列举出所有运行过或正在运行的容器:

[heql@ubuntu ~]$ docker container ls -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
8cd0489ba340        hello-world         "/hello"            2 minutes ago       Exited (0) 2 minutes ago                       blissful_brown

或者使用docker ps -a

[heql@ubuntu ~]$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
8cd0489ba340        hello-world         "/hello"            20 minutes ago      Exited (0) 20 minutes ago 

使用docker container ls,只能查看到正在运行的容器,如下命令,docker run -it centos,表示进入centos容器,这时在另一个终端使用docker container ls可以看到正在运行的centos容器, 或者使用docker ps

[heql@ubuntu ~]$ docker run -it centos
[root@c9dc077942dd /]# ls
anaconda-post.log  dev  home  lib64  mnt  proc  run   srv  tmp  var
bin                etc  lib   media  opt  root  sbin  sys  usr
[root@c9dc077942dd /]#

另一个终端:

[heql@ubuntu ~]$ docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS               NAMES
c9dc077942dd        centos              "/bin/bash"         About a minute ago   Up About a minute                       quizzical_perlman

停止容器

如果想要停止正在运行的容器,可以使用docker stop命令:

docker stop c9dc077942dd

如果在容器运行时,给容器指定了特定的名字,停止容器时,可以直接使用指定的名字:

[heql@ubuntu ~]$ docker run -it --name=test_centos centos
[heql@ubuntu ~]$ docker stop test_centos

启动容器类似:

[heql@ubuntu ~]$ docker start test_centos

删除容器

使用docker container rm可以删除容器,删除容器时,需指定容器的ID:

[heql@ubuntu ~]$ docker container ls -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                          PORTS               NAMES
c9dc077942dd        centos              "/bin/bash"         5 minutes ago       Exited (0) About a minute ago                       quizzical_perlman
f3a9294d8cac        centos              "/bin/bash"         5 minutes ago       Exited (0) 5 minutes ago                            quizzical_yonath
8cd0489ba340        hello-world         "/hello"            16 minutes ago      Exited (0) 16 minutes ago                           blissful_brown
[heql@ubuntu ~]$ docker container rm f3a9294d8cac
f3a9294d8cac
[heql@ubuntu ~]$ docker container ls -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
c9dc077942dd        centos              "/bin/bash"         5 minutes ago       Exited (0) 2 minutes ago                        quizzical_perlman
8cd0489ba340        hello-world         "/hello"            16 minutes ago      Exited (0) 16 minutes ago   

或者直接使用:docker rm f3a9294d8cac

删除所有的容器

列出所有的容器ID:

[heql@ubuntu ~]$ docker container ls -aq
feeda6f90f81
8cd0489ba340

删除所有的容器:

[heql@ubuntu ~]$ docker rm $(docker container ls -aq)
feeda6f90f81
8cd0489ba340
[heql@ubuntu ~]$ docker container ls -a 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

删除所有的已退出的容器

使用docker container ls -a -f "status=exited"可以列举出所有的已退出的容器:

[heql@ubuntu ~]$ docker container ls -a
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS                     PORTS               NAMES
6829b0656df7        centos              "/bin/bash"         About a minute ago   Up About a minute                              sad_davinci
2f359fdea718        hello-world         "/hello"            2 minutes ago        Exited (0) 2 minutes ago                       elastic_volhard
[heql@ubuntu ~]$ 
[heql@ubuntu ~]$ docker container ls -a -f "status=exited" 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
2f359fdea718        hello-world         "/hello"            2 minutes ago       Exited (0) 2 minutes ago                       elastic_volhard

使用docker container ls -a -f "status=exited" -q可以列举出所有的已退出的容器的ID:

[heql@ubuntu ~]$ docker container ls -a -f "status=exited" -q
2f359fdea718

删除所有已退出的容器:

[heql@ubuntu ~]$ docker rm $(docker container ls -a -f "status=exited" -q)
2f359fdea718
[heql@ubuntu ~]$ docker container ls -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
6829b0656df7        centos              "/bin/bash"         5 minutes ago       Up 5 minutes  

构建自己的image

创建一个hello-world目录,在该目录下创建一个hello.c的程序:

1
2
3
4
5
6
7
#include <stdio.h>

int main(int argc, char *argv[]) {
printf("hello Docker!!!\n");

return 0;
}

编译hello.c的程序:

gcc -static hello.c -o hello

在当前目录下创建如下的Dockerfile:

[heql@ubuntu hello-world]$ cat Dockerfile 
FROM scratch
LABEL maintainer="heqingliang_gzus@163.com"
ADD hello /
CMD ["/hello"]

build当前目录下的Docker:

[heql@ubuntu hello-world]$ docker build -t heql/hello-world .
Sending build context to Docker daemon  12.29kB
Step 1/4 : FROM scratch
---> 
Step 2/4 : LABEL maintainer="heqingliang_gzus@163.com"
---> Using cache
---> 8bf9dc0545a8
Step 3/4 : ADD hello /
---> Using cache
---> d169a7c1c2e1
Step 4/4 : CMD ["/hello"]
---> Using cache
---> 266076d6f19e
Successfully built 266076d6f19e
Successfully tagged heql/hello-world:latest

build成功后,可以看到生成以下image:

[heql@ubuntu hello-world]$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
heql/hello-world    latest              266076d6f19e        About a minute ago

运行image,输出以下结果:

[heql@ubuntu hello-world]$ docker run heql/hello-world
hello Docker!!!

发布镜像

类似github,docker的image也是可以push到docker image里面的,首先要在https://registry.hub.docker.com/注册账号,才能push。

首先要使用docker login命令登录docker hub,然后就可以push镜像,push的时候Tag要和登录的docker ID一致:

[heql@ubuntu hello-world]$ docker push heqingliang/hello-world
The push refers to repository [docker.io/heqingliang/hello-world]
966edc0dbbe3: Pushed 
latest: digest: sha256:603c97629b6f0ccfd7a07af90d750ca0efd52dd51d8d5b6a901f1a98ea3b2717 size: 527

push成功后,就可以在自己的docker hub看到该image:

docker_hub.png