设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客
LUPA开源社区 首页 业界资讯 技术文摘 查看内容

Docker终极指南

2015-1-12 16:46| 发布者: joejoe0332| 查看: 3184| 评论: 0|原作者: 梁晓勇|来自: http://dockerone.com

摘要: Docker入门的好文章,之前在微博上就有很多人推荐,也是2015年的新文章,DockerOne作了翻译。本教程有三个目标:说明Docker解决的问题、说明它如何解决这个问题、以及说明它使用了哪些技术来解决这个问题,这不是一 ...



镜像

我们来看一下postgresql的一个镜像:
[{
"AppArmorProfile": "",
"Args": [
    "postgres"
],
"Config": {
    "AttachStderr": true,
    "AttachStdin": false,
    "AttachStdout": true,
    "Cmd": [
        "postgres"
    ],
    "CpuShares": 0,
    "Cpuset": "",
    "Domainname": "",
    "Entrypoint": [
        "/docker-entrypoint.sh"
    ],
    "Env": [
        "PATH=/usr/lib/postgresql/9.3/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
        "LANG=en_US.utf8",
        "PG_MAJOR=9.3",
        "PG_VERSION=9.3.5-1.pgdg70 1",
        "PGDATA=/var/lib/postgresql/data"
    ],
    "ExposedPorts": {
        "5432/tcp": {}
    },
    "Hostname": "6334a2022f21",
    "Image": "postgres",
    "MacAddress": "",
    "Memory": 0,
    "MemorySwap": 0,
    "NetworkDisabled": false,
    "OnBuild": null,
    "OpenStdin": false,
    "PortSpecs": null,
    "StdinOnce": false,
    "Tty": false,
    "User": "",
    "Volumes": {
        "/var/lib/postgresql/data": {}        
    },
    "WorkingDir": ""
},
"Created": "2015-01-03T23:56:12.354896658Z",
"Driver": "devicemapper",
"ExecDriver": "native-0.2",
"HostConfig": {
    "Binds": null,
    "CapAdd": null,
    "CapDrop": null,
    "ContainerIDFile": "",
    "Devices": null,
    "Dns": null,
    "DnsSearch": null,
    "ExtraHosts": null,
    "IpcMode": "",
    "Links": null,
    "LxcConf": null,
    "NetworkMode": "",
    "PortBindings": null,
    "Privileged": false,
    "PublishAllPorts": false,
    "RestartPolicy": {
        "MaximumRetryCount": 0,
        "Name": ""
    },
    "SecurityOpt": null,
    "VolumesFrom": [
        "bestwebappever.dev.db-data"
    ]
},
"HostnamePath": "/mnt/docker/containers/6334a2022f213f9534b45df33c64437081a38d50c7f462692b019185b8cbc6da/hostname",
"HostsPath": "/mnt/docker/containers/6334a2022f213f9534b45df33c64437081a38d50c7f462692b019185b8cbc6da/hosts",
"Id": "6334a2022f213f9534b45df33c64437081a38d50c7f462692b019185b8cbc6da",
"Image": "aaab661c1e3e8da2d9fc6872986cbd7b9ec835dcd3886d37722f1133baa3d2db",
"MountLabel": "",
"Name": "/bestwebappever.dev.db",
"NetworkSettings": {
    "Bridge": "docker0",
    "Gateway": "172.17.42.1",
    "IPAddress": "172.17.0.176",
    "IPPrefixLen": 16,
    "MacAddress": "02:42:ac:11:00:b0",
    "PortMapping": null,    
    "Ports": {
        "5432/tcp": null
    }
},
"Path": "/docker-entrypoint.sh",
"ProcessLabel": "",
"ResolvConfPath": "/mnt/docker/containers/6334a2022f213f9534b45df33c64437081a38d50c7f462692b019185b8cbc6da/resolv.conf",
"State": {
    "Error": "",
    "ExitCode": 0,
    "FinishedAt": "0001-01-01T00:00:00Z",
    "OOMKilled": false,
    "Paused": false,
    "Pid": 21654,
    "Restarting": false,
    "Running": true,
    "StartedAt": "2015-01-03T23:56:42.003405983Z"
},
"Volumes": {
    "/var/lib/postgresql/data": "/mnt/docker/vfs/dir/5ac73c52ca86600a82e61279346dac0cb3e173b067ba9b219ea044023ca67561",
    "postgresql_data": "/mnt/docker/vfs/dir/abace588b890e9f4adb604f633c280b9b5bed7d20285aac9cc81a84a2f556034"
},
"VolumesRW": {
    "/var/lib/postgresql/data": true,
    "postgresql_data": true
}
}
]


就是这样,镜像只是一个json,它指定了从该镜像运行的容器的特性,union装载点保存在哪里,要暴露什么端口等等。每个镜像与一个union文件系统相关联,每个Docker上的union文件系统都有一个上层,就像是计算机科技树(不像其他树有一大堆的家族)。如果它看起来有点吓人或有些东西串不起来,不要担心,这只是出于教学目的,你并不会直接处理这些文件。

容器

容器之所以是短暂的,是因为当你从镜像上创建一个容器,Docker会创建一个空白的union文件系统加载在与该镜像关联的union文件系统之上。

由于union文件系统是空白的,这意味着没有变化会被应用到镜像的文件系统上,你创建的变化会得到体现,但是当容器停止,该容器的union文件系统会被丢弃,留下的是你启动时的原始镜像文件系统。除非你创建一个新的镜像,或制作一个卷,你所做的变化在容器停止时都会消失。

卷所做的是在容器内指定一个目录,以便在union文件系统之外保存它。

这是一个bestwebappever的容器:
[{
"AppArmorProfile": "",
"Args": [],
"Config": {
    "AttachStderr": true,
    "AttachStdin": false,
    "AttachStdout": true,
    "Cmd": [
        "/sbin/my_init"
    ],
    "CpuShares": 0,
    "Cpuset": "",
    "Domainname": "",
    "Entrypoint": null,
    "Env": [
        "DJANGO_CONFIGURATION=Local",
        "HOME=/root",
        "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
        "TALPOR_ENVIRONMENT=local",
        "TALPOR_DIR=/opt/bestwebappever"
    ],
    "ExposedPorts": {
        "80/tcp": {}
    },
    "Hostname": "44a87fdaf870",
    "Image": "talpor/bestwebappever:dev",
    "MacAddress": "",
    "Memory": 0,
    "MemorySwap": 0,
    "NetworkDisabled": false,
    "OnBuild": null,
    "OpenStdin": false,
    "PortSpecs": null,
    "StdinOnce": false,
    "Tty": false,
    "User": "",
    "Volumes": {
        "/opt/bestwebappever": {}
    },
    "WorkingDir": "/opt/bestwebappever"
},
"Created": "2015-01-03T23:56:15.378511619Z",
"Driver": "devicemapper",
"ExecDriver": "native-0.2",
"HostConfig": {
    "Binds": [
        "/home/german/bestwebappever/:/opt/bestwebappever:rw"
    ],
    "CapAdd": null,
    "CapDrop": null,
    "ContainerIDFile": "",
    "Devices": null,
    "Dns": null,
    "DnsSearch": null,
    "ExtraHosts": null,
    "IpcMode": "",
    "Links": [
        "/bestwebappever.dev.db:/bestwebappever.dev.app/db",
        "/bestwebappever.dev.redis:/bestwebappever.dev.app/redis"
    ],
    "LxcConf": null,
    "NetworkMode": "",
    "PortBindings": {
        "80/tcp": [
            {
                "HostIp": "",
                "HostPort": "8887"
            }
        ]
    },
    "Privileged": false,
    "PublishAllPorts": false,
    "RestartPolicy": {
        "MaximumRetryCount": 0,
        "Name": ""
    },
    "SecurityOpt": null,
    "VolumesFrom": [
        "bestwebappever.dev.requirements-data"
    ]
},
"HostnamePath": "/mnt/docker/containers/44a87fdaf870281e86160e9e844b8987cfefd771448887675fed99460de491c4/hostname",
"HostsPath": "/mnt/docker/containers/44a87fdaf870281e86160e9e844b8987cfefd771448887675fed99460de491c4/hosts",
"Id": "44a87fdaf870281e86160e9e844b8987cfefd771448887675fed99460de491c4",
"Image": "b84804fac17b61fe8f344359285186f1a63cd8c0017930897a078cd09d61bb60",
"MountLabel": "",
"Name": "/bestwebappever.dev.app",
"NetworkSettings": {
    "Bridge": "docker0",
    "Gateway": "172.17.42.1",
    "IPAddress": "172.17.0.179",
    "IPPrefixLen": 16,
    "MacAddress": "02:42:ac:11:00:b3",
    "PortMapping": null,
    "Ports": {
        "80/tcp": [
            {
                "HostIp": "0.0.0.0",
                "HostPort": "8887"
            }
        ]
    }
},
"Path": "/sbin/my_init",
"ProcessLabel": "",
"ResolvConfPath": "/mnt/docker/containers/44a87fdaf870281e86160e9e844b8987cfefd771448887675fed99460de491c4/resolv.conf",
"State": {
    "Error": "",
    "ExitCode": 0,
    "FinishedAt": "0001-01-01T00:00:00Z",
    "OOMKilled": false,
    "Paused": false,
    "Pid": 21796,
    "Restarting": false,
    "Running": true,
    "StartedAt": "2015-01-03T23:56:47.537259546Z"
},
"Volumes": {
    "/opt/bestwebappever": "/home/german/bestwebappever",
    "requirements_data": "/mnt/docker/vfs/dir/bc14bec26ca311d5ed9f2a83eebef872a879c9e2f1d932470e0fd853fe8be336"
},
"VolumesRW": {
    "/opt/bestwebappever": true,
    "requirements_data": true
}
}
]

基本上与镜像相同,不过现在还指定了一些暴露给宿主的端口,也声明了卷位于宿主的位置,容器状态是从现在直到结束,等等。与前面一样,如果它看起来让人生畏,不要担心,你不会直接处理这些json。

超级、无比简单的步骤说明

第一步,安装Docker

Docker命令工具需要root权限才能工作。你可以将你的用户放入docker组来避免每次都要使用sudo。

第二步,使用以下命令从公共registry下载一个镜像:
$> docker pull ubuntu:latest
ubuntu:latest: The image you are pulling has been verified
3b363fd9d7da: Pull complete
.....<bunch of downloading-stuff output>.....
8eaa4ff06b53: Pull complete
Status: Downloaded newer image for ubuntu:latest
$>

这个公共registry上有你需要的几乎所有东西的镜像:Ubuntu、Fedora、Postgresql、MySQL、Jenkins、Elasticsearch、Redis等等。Docker开发人员在这个公共registry里维护着数个镜像,不过你能从上面拉取大量来自用户发布的自建镜像。

也许你需要或想要一个私有的registry(用于开发应用之类的容器),你可以先看看这个现在有好几个方式可以设置自己的私有registry你也可以买一个

第三步,列出你的镜像:
$> docker images
REPOSITORY  TAG     IMAGE ID      CREATED     VIRTUAL SIZE
ubuntu      latest  8eaa4ff06b53  4 days ago  192.7 MB

第四步,从该镜像上创建一个容器。
$> docker run --rm -ti ubuntu /bin/bash
root@4638a40c2fbb:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root......
root@4638a40c2fbb:/# exit

上一条命令的简要说明:
  • --rm:告诉Docker一旦运行的进程退出就删除容器。这在进行测试时非常有用,可免除杂乱
  • -ti:告诉Docker分配一个伪终端并进入交互模式。这将进入到容器内,对于快速原型开发或尝试很有用,但不要在生产容器中打开这些标志
  • ubuntu:这是容器立足的镜像
  • /bin/bash:要运行的命令,因为我们以交互模式启动,它将显示一个容器的提示符

在运行run命令时,你可指定链接、卷、端口、窗口名称(如果你没提供,Docker将分配一个默认名称)等等。

现在,我们在后台运行一个容器:
$> docker run -d ubuntu ping 8.8.8.8
31c68e9c09a0d632caae40debe13da3d6e612364198e2ef21f842762df4f987f
$>

输出的是分配的ID,因为是随机的,你的将有所不同。我们来检查一下容器是否起来了:
$> docker ps
CONTAINER ID IMAGE         COMMAND         CREATED        STATUS        PORTS  NAMES
31c68e9c09a0 ubuntu:latest "ping 8.8.8.8"  2 minutes ago  Up 2 minutes         loving_mcclintock

就在那,它被自动分配了一个叫loving_mcclintock的名称。我们看看容器里正在发生什么:
$> docker exec -ti loving_mcclintock /bin/bash
root@31c68e9c09a0:/# ps -aux|grep ping
root 1 0.0 0.0 6504 636 ? Ss 20:46 0:00 ping 8.8.8.8
root@31c68e9c09a0:/# exit

我们所做的是在容器里运行程序,这里的程序是/bin/bash。-ti标志与docker run的作用相同,将我们放置到容器的控制台里。


酷毙

雷人

鲜花

鸡蛋

漂亮
  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部