Docker基础入门
docker概述
docker是一个用于开发,交付和运行应用程序的开放平台。
docker优势
更快速的交付和部署
对于开发人员 - build once, run anywhere
容器意味着环境隔离和可重复性。开发人员只需为应用创建一次运行环境,然后打包成容器便可在其他机器上运行。另外,容器环境与所在的 host 环境是隔离的,就像虚拟机一样,但更快更简单。
对于运维人员 - configure once, run anything
只需要配置好标准的 runtime 环境,服务器就可以运行任何容器。这使得运维人员的工作变得更高效,一致和可重复。容器消除了开发、测试、生产环境的不一致性。
更高效的虚拟化
docker 容器的运行不需要额外的 hypervisor 支持,它是内核级的虚拟化,因此可以实现更高的性能和效率。
更轻松的迁移和扩展
docker 容器几乎可以在任意的平台上运行,包括物理机、虚拟机、公有云、私有云、个人电脑、服务器等。 这种兼容性可以让用户把一个应用程序从一个平台直接迁移到另外一个。
更简单的管理
使用 docker,只需要小小的修改,就可以替代以往大量的更新工作。所有的修改都以增量的方式被分发和更新,从而实现自动化并且高效的管理。
docker engine
docker engine是具有以下主要组件的客户端-服务器应用程序:
服务器是一种长期运行的程序,称为守护程序进程( dockerd命令)。
rest api,它指定程序可以用来与守护程序进行通信并指示其操作的接口。
命令行界面(cli)客户端(docker命令)。
cli使用docker rest api通过脚本或直接cli命令来控制docker守护程序或与docker守护程序进行交互。
许多其他docker应用程序都使用基础api和cli。
docker架构
docker 使用c/s (客户端/服务器)体系的架构,docker 客户端与 docker 守护进程通信,docker 守护进程负责构建,运行和分发 docker 容器。docker 客户端和守护进程可以在同一个系统上运行,也可以将 docker 客户端连接到远程 docker 守护进程。docker 客户端和守护进程使用 rest api 通过unix套接字或网络接口进行通信。
docker damon:dockerd,用来监听 docker api 的请求和管理 docker 对象,比如镜像、容器、网络和 volume。
docker client:docker client 是我们和 docker 进行交互的最主要的方式方法,比如我们可以通过 docker run 命令来运行一个容器,然后我们的这个 client 会把命令发送给上面的 dockerd,让他来做真正事情。
docker三个基本概念
docker registry:用来存储 docker 镜像的仓库,docker hub 是 docker 官方提供的一个公共仓库,而且 docker 默认也是从 docker hub 上查找镜像的,当然你也可以很方便的运行一个私有仓库,当我们使用 docker pull 或者 docker run 命令时,就会从我们配置的 docker 镜像仓库中去拉取镜像,使用 docker push 命令时,会将我们构建的镜像推送到对应的镜像仓库中。
images:镜像是一个只读模板,带有创建 docker 容器的说明,一般来说的,镜像会基于另外的一些基础镜像并加上一些额外的自定义功能。比如,你可以构建一个基于 centos 的镜像,然后在这个基础镜像上面安装一个 nginx 服务器,这样就可以构成一个属于我们自己的镜像了。
containers:容器是一个镜像的可运行的实例,可以使用 docker rest api 或者 cli 来操作容器,容器的实质是进程,但与直接在宿主机执行的进程不同,容器进程运行于属于自己的独立的命名空间。因此容器可以拥有自己的 root 文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 id 空间。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。这种特性使得容器封装的应用比直接在宿主运行更加安全。
底层技术支持:
docker用go编写、namespaces(做隔离)、cgroups(做资源限制)、unionfs(镜像和容器的分层) the-underlying-technology docker 底层架构分析
安装
直接前往官方文档选择合适的平台安装即可,比如我们这里想要在centos系统上安装 docker,这前往地址https://docs.docker.com/install/linux/docker-ce/centos/根据提示安装即可。
安装所需的软件包
sudo yum install -y yum-utils \ device-mapper-persistent-data \ lvm2
添加软件仓库,我们这里使用稳定版 docker,执行下面命令添加 yum 仓库地址:
sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo
安装 docker ce
yum install docker-ce
启动 docker ce
$ sudo systemctl enable docker $ sudo systemctl start docker
查看版本号
[root@localhost ~]# docker version client: docker engine - community version: 19.03.4 api version: 1.40 go version: go1.12.10 git commit: 9013bf583a built: fri oct 18 15:52:22 2019 os/arch: linux/amd64 experimental: false server: docker engine - community engine: version: 19.03.4 api version: 1.40 (minimum version 1.12) go version: go1.12.10 git commit: 9013bf583a built: fri oct 18 15:50:54 2019 os/arch: linux/amd64 experimental: false containerd: version: 1.2.10 gitcommit: b34a5c8af56e510852c35414db4c1f4fa6172339 runc: version: 1.0.0-rc8+dev gitcommit: 3e425f80a8c931f88e6d94a8c831b9d5aa481657 docker-init: version: 0.18.0 gitcommit: fec3683 [root@localhost ~]#
运行第一个容器
环境就绪,马上运行第一个容器,执行命令:
docker run -d -p 80:80 httpd 第一次需要下载镜像 可能比较慢 这就需要做镜像加速
镜像加速器
国内从 docker hub 拉取镜像有时会遇到困难,此时可以配置镜像加速器
对于使用 systemd 的系统,请在 /etc/docker/daemon.json 中写入如下内容(如果文件不存在请新建该文件) { "registry-mirrors": [ "https://dockerhub.azk8s.cn", "https://reg-mirror.qiniu.com" ] } 注意,一定要保证该文件符合 json 规范,否则 docker 将不能启动。 之后重新启动服务
检查加速器是否生效
[root@localhost docker]# docker info |grep registry -a 10 registry: https://index.docker.io/v1/ labels: experimental: false insecure registries: 127.0.0.0/8 registry mirrors: https://dockerhub.azk8s.cn/ https://reg-mirror.qiniu.com/ live restore enabled: false
启动一个容器:
[root@muyudembp ~]# docker run ubuntu:16.04 /bin/echo 'hello world' unable to find image 'ubuntu:16.04' locally 16.04: pulling from library/ubuntu e80174c8b43b: pull complete d1072db285cc: pull complete 858453671e67: pull complete 3d07b1124f98: pull complete digest: sha256:bb5b48c7750a6a8775c74bcb601f7e5399135d0a06de004d000e05fd25c1a71c status: downloaded newer image for ubuntu:16.04 hello world [root@muyudembp ~]# docker run ubuntu:16.04 /bin/echo 'hello world' hello world
查看镜像的历史命令
[root@muyudembp ~]# docker history ubuntu:16.04 image created created by size comment 5f2bf26e3524 less than a second ago /bin/sh -c #(nop) cmd ["/bin/bash"] 0b <missing> less than a second ago /bin/sh -c mkdir -p /run/systemd && echo 'do… 7b <missing> less than a second ago /bin/sh -c set -xe && echo '#!/bin/sh' > /… 745b <missing> less than a second ago /bin/sh -c rm -rf /var/lib/apt/lists/* 0b <missing> less than a second ago /bin/sh -c #(nop) add file:9511990749b593a6f… 123mb
进入容器
[root@muyudembp ~]# docker run -it ubuntu:16.04 /bin/bash root@247c977ce6dc:/# ls bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var root@247c977ce6dc:/#
启动 关闭容器
[root@muyudembp ~]# docker ps container id image command created status ports names 247c977ce6dc ubuntu:16.04 "/bin/bash" 7 minutes ago up 7 minutes youthful_hamilton 6fe5c402d589 httpd "httpd-foreground" 5 hours ago up 5 hours 0.0.0.0:80->80/tcp sad_dijkstra [root@muyudembp ~]# docker stop 6fe5c402d589 6fe5c402d589 [root@muyudembp ~]# docker ps container id image command created status ports names 247c977ce6dc ubuntu:16.04 "/bin/bash" 7 minutes ago up 7 minutes youthful_hamilton [root@muyudembp ~]# docker start 6fe5c402d589 6fe5c402d589 [root@muyudembp ~]# docker ps container id image command created status ports names 247c977ce6dc ubuntu:16.04 "/bin/bash" 7 minutes ago up 7 minutes youthful_hamilton 6fe5c402d589 httpd "httpd-foreground" 5 hours ago up 1 second 0.0.0.0:80->80/tcp sad_dijkstra [root@muyudembp ~]# docker rm 247c977ce6dc error response from daemon: you cannot remove a running container 247c977ce6dcc47e043b4d9ef02c95b4d7d21e32009bff425314724315e4bea4. stop the container before attempting removal or force remove 强制关闭在运行的容器 [root@muyudembp ~]# docker rm -f 247c977ce6dc 247c977ce6dc [root@muyudembp ~]# docker ps container id image command created status ports names 6fe5c402d589 httpd "httpd-foreground" 5 hours ago up 2 minutes 0.0.0.0:80->80/tcp sad_dijkstra
镜像相关操作
[root@muyudembp ~]# docker rmi -f 5f2bf26e3524 untagged: ubuntu:16.04 untagged: ubuntu@sha256:bb5b48c7750a6a8775c74bcb601f7e5399135d0a06de004d000e05fd25c1a71c deleted: sha256:5f2bf26e35249d8b47f002045c57b2ea9d8ba68704f45f3c209182a7a2a9ece5 [root@muyudembp ~]# docker image ls repository tag image id created size httpd latest d3017f59d5e2 17 hours ago 165mb
docker commit定制镜像
镜像是容器的基础,每次执行docker run的时候都会指定哪个镜像作为容器运行的基础。在之前的例子中,我们所使用的都是来自于 docker hub 的镜像。直接使用这些镜像是可以满足一定的需求,而当这些镜像无法直接满足需求时,我们就需要定制这些镜像。
现在让我们用httpd镜像做个示例。
docker run --name webserver -d -p 80:80 httpd
这条命令会用 httpd 镜像启动一个容器,命名为 webserver,并且映射了 80 端口,这样我们可以用浏览器去访问这个 web 服务器。
[root@muyudembp ~]# curl localhost <html><body><h1>it works!</h1></body></html> [root@muyudembp ~]# docker exec -it 543f2ad89f8e /bin/bash root@543f2ad89f8e:/usr/local/apache2# echo "<h1>hello, docker!</h1>" > /usr/local/apache2/htdocs 退出容器 [root@muyudembp ~]# curl localhost <h1>hello, docker!</h1> 我们可以用下面的命令将容器保存为镜像: [root@muyudembp ~]# docker commit \ > --author "muyu" \ > --message "修改了默认首页" \ > webserver \ > httpd:v2 sha256:229d8c3a7577be285e858f80c1e97dad5ddfb504fbcd5b4f1b3ad4fa40935712 [root@muyudembp ~]# docker images repository tag image id created size httpd v2 229d8c3a7577 11 seconds ago 165mb httpd latest d3017f59d5e2 17 hours ago 165mb [root@muyudembp ~]# docker history 229d8c3a7577 image created created by size comment 229d8c3a7577 about a minute ago httpd-foreground 31b 修改了默认首页 d3017f59d5e2 17 hours ago /bin/sh -c #(nop) cmd ["httpd-foreground"] 0b <missing> 17 hours ago /bin/sh -c #(nop) expose 80 0b <missing> 17 hours ago /bin/sh -c #(nop) copy file:c432ff61c4993ecd… 138b <missing> 17 hours ago /bin/sh -c #(nop) stopsignal winch 0b <missing> 17 hours ago /bin/sh -c set -eux; savedaptmark="$(apt-m… 60.7mb <missing> 2 weeks ago /bin/sh -c #(nop) env httpd_patches= 0b <missing> 2 weeks ago /bin/sh -c #(nop) env httpd_sha256=133d4829… 0b <missing> 2 weeks ago /bin/sh -c #(nop) env httpd_version=2.4.41 0b <missing> 2 weeks ago /bin/sh -c set -eux; apt-get update; apt-g… 35.4mb <missing> 2 weeks ago /bin/sh -c #(nop) workdir /usr/local/apache2 0b <missing> 2 weeks ago /bin/sh -c mkdir -p "$httpd_prefix" && chow… 0b <missing> 2 weeks ago /bin/sh -c #(nop) env path=/usr/local/apach… 0b <missing> 2 weeks ago /bin/sh -c #(nop) env httpd_prefix=/usr/loc… 0b <missing> 2 weeks ago /bin/sh -c #(nop) cmd ["bash"] 0b <missing> 2 weeks ago /bin/sh -c #(nop) add file:74b2987cacab5a6b0… 69.2mb [root@muyudembp ~]# docker run --name webserver2 -d -p 81:80 httpd:v2 693745577ac0d47dc88680dff44afa3749ac88c39ad55deea1802c191bcb9542 [root@muyudembp ~]# curl localhost:81 <h1>hello, docker!</h1>
至此,我们第一次完成了定制镜像,使用的是docker commit命令,手动操作给旧的镜像添加了新的一层,形成新的镜像,对镜像多层存储应该有了更直观的感觉。
但是定制镜像不建议这么做 定制镜像应该使用dockerfile来完成
命令整理:
容器操作:
docker create # 创建一个容器但是不启动它 docker run # 创建并启动一个容器 docker stop # 停止容器运行,发送信号sigterm docker start # 启动一个停止状态的容器 docker restart # 重启一个容器 docker rm # 删除一个容器 docker kill # 发送信号给容器,默认sigkill docker attach # 连接(进入)到一个正在运行的容器 docker wait # 阻塞一个容器,直到容器停止运行
获取容器信息:
docker ps # 显示状态为运行(up)的容器 docker ps -a # 显示所有容器,包括运行中(up)的和退出的(exited) docker inspect # 深入容器内部获取容器所有信息 docker logs # 查看容器的日志(stdout/stderr) docker events # 得到docker服务器的实时的事件 docker port # 显示容器的端口映射 docker top # 显示容器的进程信息 docker diff # 显示容器文件系统的前后变化 docker system df # 查看镜像、容器、数据卷所占用的空间。
导出容器:
docker cp # 从容器里向外拷贝文件或目录 docker export # 将容器整个文件系统导出为一个tar包,不带layers、tag等信息
执行:
docker exec # 在容器里执行一个命令,可以执行bash进入交互式
镜像操作:
docker images # 显示本地所有的镜像列表 docker import # 从一个tar包创建一个镜像,往往和export结合使用 docker build # 使用dockerfile创建镜像(推荐) docker commit # 从容器创建镜像 docker rmi # 删除一个镜像 docker load # 从一个tar包创建一个镜像,和save配合使用 docker save # 将一个镜像保存为一个tar包,带layers和tag信息 docker history # 显示生成一个镜像的历史命令 docker tag # 为镜像起一个别名
镜像仓库(registry)操作:
docker login # 登录到一个registry docker search # 从registry仓库搜索镜像 docker pull # 从仓库下载镜像到本地 docker push # 将一个镜像push到registry仓库中