Docker 是一个开源的应用容器引擎,基于 Go 语言 并听从Apache2.0协议开源。html
Docker 可让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,而后发布到任何流行的 Linux 机器上,也能够实现虚拟化。python
容器是彻底使用沙箱机制,相互之间不会有任何接口(相似 iPhone 的 app),更重要的是容器性能开销极低。linux
Docker 从 17.03 版本以后分为 CE(Community Edition: 社区版) 和 EE(Enterprise Edition: 企业版),咱们用社区版就能够了。nginx
Docker 使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和建立Docker容器。git
Docker 容器经过 Docker 镜像来建立。web
容器与镜像的关系相似于面向对象编程中的对象与类:
镜像---->类
容器---->对象docker
下载安装包:apache
[root@jin-10 ~]# curl https://download.docker.com/linux/centos/docker-ce.repo -o /etc/yum.repos.d/docker.repo
安装:编程
yum install -y docker-ce
安装后可查看Docker的版本信息:json
[root@jin-10 ~]# docker --version Docker version 19.03.1, build 74b1e89
鉴于国内网络问题,后续拉取 Docker 镜像十分缓慢,咱们能够经过配置来解决。此处以阿里云为例:
复制这个地址,而后编辑文件/etc/docker/daemon.json,写入以下内容:
{ "registry-mirrors": ["https://qrel1k8y.mirror.aliyuncs.com"] }
配置完后,需重启docker服务使其生效。
启动Docker服务:
[root@jin-10 ~]# systemctl start docker [root@jin-10 ~]# ps aux|grep docker root 1838 3.0 6.5 569176 65524 ? Ssl 09:10 0:09 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock root 1995 0.0 0.1 112724 996 pts/0 S+ 09:15 0:00 grep --color=auto docker
测试运行 hello-world:
因为本地没有hello-world这个镜像,因此会下载一个hello-world的镜像,并在容器内运行。
[root@jin-10 ~]# docker run hello-world Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 1b930d010525: Pull complete Digest: sha256:451ce787d12369c5df2a32c85e5a03d52cbcef6eb3586dd03075f3034f10adcd Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://hub.docker.com/ For more examples and ideas, visit: https://docs.docker.com/get-started/
Docker-ce的删除命令:
systemctl remove docker-ce rm -rf /var/lib/docker
下面仍是以运行Hello World为例:
[root@jin-10 ~]# docker run centos /bin/echo 'Hello World!' Unable to find image 'centos:latest' locally latest: Pulling from library/centos d8d02d457314: Pull complete Digest: sha256:307835c385f656ec2e2fec602cf093224173c51119bbebd602c53c3653a3d6eb Status: Downloaded newer image for centos:latest Hello World!
交互式的方式运行容器:
[root@jin-10 ~]# docker run -i -t centos /bin/bash [root@ab1c701e7fe3 /]# ls anaconda-post.log dev home lib64 mnt proc run srv tmp var bin etc lib media opt root sbin sys usr [root@ab1c701e7fe3 /]# cat /proc/version Linux version 3.10.0-957.27.2.el7.x86_64 (mockbuild@kbuilder.bsys.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC) ) #1 SMP Mon Jul 29 17:46:05 UTC 2019 [root@ab1c701e7fe3 /]# pwd /
后台方式启动容器:
[root@jin-10 ~]# docker run -d centos /bin/bash -c "while true; do echo hello world; sleep 1; done" 5830d6e57f238d97de8048630bec6c74b897d95723d326fbed5a36de4fab9397
能够看到,咱们输入以上的命令后,并无输出hello world内容,而是返回了一串字符编码。这个字符编码叫作容器ID,对每一个容器来讲都是惟一的,咱们能够经过容器ID来查看对应的容器发生了什么。 docker ps 命令能够查看是否有容器在运行:
[root@jin-10 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5830d6e57f23 centos "/bin/bash -c 'while…" 13 seconds ago Up 11 seconds great_taussig
docker logs(后面接容器ID或容器name)命令,能够查看容器内的标准输出:
[root@jin-10 ~]# docker logs 5830d6e57f23 hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world
能够看到,其实以前输入的命令,实际上是在后台一直运行。 docker stop(容器ID或容器name)命令能够中止正在运行的容器:
[root@jin-10 ~]# docker stop 5830d6e57f23 5830d6e57f23 [root@jin-10 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
咱们在docker容器中运行一个 Python Flask 应用来运行一个web应用。
[root@jin-10 ~]# docker pull training/webapp Using default tag: latest latest: Pulling from training/webapp [DEPRECATION NOTICE] registry v2 schema1 support will be removed in an upcoming release. Please contact admins of the docker.io registry NOW to avoid future disruption. e190868d63f8: Pull complete 909cd34c6fd7: Pull complete 0b9bfabab7c1: Pull complete a3ed95caeb02: Pull complete 10bbbc0fc0ff: Pull complete fca59b508e9f: Pull complete e7ae2541b15b: Pull complete 9dd97ef58ce9: Pull complete a4c1b0cb7af7: Pull complete Digest: sha256:06e9c1983bd6d5db5fba376ccd63bfa529e8d02f23d5079b8f74a616308fb11d Status: Downloaded newer image for training/webapp:latest docker.io/training/webapp:latest [root@jin-10 ~]# docker run -d -P training/webapp python app.py b8ed64647e26a3273c718b6a7ebec808f615d486dbb8cb62df73de037fcd847c
[root@jin-10 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b8ed64647e26 training/webapp "python app.py" About a minute ago Up 57 seconds 0.0.0.0:32768->5000/tcp admiring_ride
能够看到,此处多了端口(PORTS)信息:0.0.0.0:32768->5000/tcp
Docker 开放了 5000 端口(默认 Python Flask 端口)映射到主机端口 32768 上。
咱们能够经过浏览器访问WEB应用:
咱们也能够经过 -p 参数来设置不同的端口:
[root@jin-10 ~]# docker run -d -p 5000:5000 training/webapp python app.py 30dbbec04fcdd58f82cb642e913f26457ac985428be4d498729ceb4beb821e96 [root@jin-10 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 30dbbec04fcd training/webapp "python app.py" 8 seconds ago Up 5 seconds 0.0.0.0:5000->5000/tcp naughty_golick b8ed64647e26 training/webapp "python app.py" 7 minutes ago Up 7 minutes 0.0.0.0:32768->5000/tcp admiring_ride
咱们可使用 docker port 查看指定 (ID 或者名字)容器的某个肯定端口映射到宿主机的端口号,以上面为例:
[root@jin-10 ~]# docker port b8ed64647e26 5000/tcp -> 0.0.0.0:32768 [root@jin-10 ~]# docker port admiring_ride 5000/tcp -> 0.0.0.0:32768
docker logs [ID或者名字] 能够查看容器内部的标准输出:
[root@jin-10 ~]# docker logs admiring_ride * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit) 192.168.154.1 - - [26/Aug/2019 02:20:54] "GET / HTTP/1.1" 200 - 192.168.154.1 - - [26/Aug/2019 02:20:54] "GET /favicon.ico HTTP/1.1" 404 -
此处咱们还可使用参数-f让 docker logs 像使用 tail -f 同样来输出容器内部的标准输出。
docker top(容器ID或容器name) 来查看容器内部运行的进程。
[root@jin-10 ~]# docker top admiring_ride UID PID PPID C STIME TTY TIME CMD root 4120 4103 0 10:14 ? 00:00:00 python app.py
docker inspect 命令能够查看 Docker 的底层信息。它会返回一个 JSON 文件记录着 Docker 容器的配置和状态信息。
[root@jin-10 ~]# docker stop admiring_ride admiring_ride
已经中止的容器,咱们可使用命令 docker start 来启动。
[root@jin-10 ~]# docker start admiring_ride admiring_ride
docker ps -l 查询最后一次建立的容器:
[root@jin-10 ~]# docker ps -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 30dbbec04fcd training/webapp "python app.py" 13 minutes ago Up 13 minutes 0.0.0.0:5000->5000/tcp naughty_golick
删除容器时,容器必须是中止状态,不然会报错:
[root@jin-10 ~]# docker rm admiring_ride Error response from daemon: You cannot remove a running container b8ed64647e26a3273c718b6a7ebec808f615d486dbb8cb62df73de037fcd847c. Stop the container before attempting removal or force remove [root@jin-10 ~]# docker stop admiring_ride admiring_ride [root@jin-10 ~]# docker rm admiring_ride admiring_ride
当运行容器时,使用的镜像若是在本地中不存在,docker 就会自动从 docker 镜像仓库中下载,默认是从 Docker Hub 公共镜像源下载。
docker images 列出本地主机上的镜像:
[root@jin-10 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE centos latest 67fa590cfc1c 5 days ago 202MB hello-world latest fce289e99eb9 7 months ago 1.84kB training/webapp latest 6fae60ef3446 4 years ago
当咱们在本地主机上使用一个不存在的镜像时 Docker 就会自动下载这个镜像。若是咱们想预先下载这个镜像,咱们可使用 docker pull 命令来下载它。
[root@jin-10 ~]# docker pull nginx Using default tag: latest latest: Pulling from library/nginx 1ab2bdfe9778: Pull complete a17e64cfe253: Pull complete e1288088c7a8: Pull complete Digest: sha256:53ddb41e46de3d63376579acf46f9a41a8d7de33645db47a486de9769201fec9 Status: Downloaded newer image for nginx:latest docker.io/library/nginx:latest
[root@jin-10 ~]# docker search httpd NAME DESCRIPTION STARS OFFICIAL AUTOMATED httpd The Apache HTTP Server Project 2614 [OK] centos/httpd 24 [OK] centos/httpd-24-centos7 Platform for running Apache httpd 2.4 or bui… 22 armhf/httpd The Apache HTTP Server Project 8 arm32v7/httpd The Apache HTTP Server Project 8 salim1983hoop/httpd24 Dockerfile running apache config 2 [OK] lead4good/httpd-fpm httpd server which connects via fcgi proxy h… 1 [OK] rgielen/httpd-image-simple Docker image for simple Apache httpd based o… 1 [OK] manageiq/httpd_configmap_generator Httpd Configmap Generator 0 [OK]
[root@jin-10 ~]# docker pull nginx Using default tag: latest latest: Pulling from library/nginx 1ab2bdfe9778: Pull complete a17e64cfe253: Pull complete e1288088c7a8: Pull complete Digest: sha256:53ddb41e46de3d63376579acf46f9a41a8d7de33645db47a486de9769201fec9 Status: Downloaded newer image for nginx:latest docker.io/library/nginx:latest
当咱们从docker镜像仓库中下载的镜像不能知足咱们的需求时,咱们能够经过如下两种方式对镜像进行更改:
[root@jin-10 ~]# docker run -i -t centos /bin/bash [root@101530c1659a /]# yum install -y net-tools ...... Installed: net-tools.x86_64 0:2.0-0.24.20131004git.el7 Complete! [root@101530c1659a /]# exit exit
咱们能够经过命令 docker commit来提交容器副本:
[root@jin-10 ~]# docker commit -m="yum install net-tools" -a="jin" 101530c1659a centos:v2 sha256:e487a99a4de9733ed613d1f79fdadc683e3e1a91fcf0f1e10e6d106d6222bd76
参数说明以下:
命令 docker build,能够从零开始来建立一个新的镜像。须要建立一个 Dockerfile 文件,其中包含一组指令来告诉 Docker 如何构建咱们的镜像。 咱们建立Dockerfile文件,并写入如下内容:
FROM centos:6.7 MAINTAINER jin "jin@linux.com" RUN /bin/echo 'root:123456' |chpasswd RUN /useradd jin RUN /bin/echo 'jin:123456' |chpasswd RUN /bin/echo -e "LANG=\"en_US.UTF-8\"" >/etc/default/local EXPOSE 22 EXPOSE 80 CMD /usr/sbin/sshd -D
每个指令都会在镜像上建立一个新的层,每个指令的前缀都必须是大写的。
咱们使用 Dockerfile 文件,经过 docker build 命令来构建一个镜像:
[root@jin-10 ~]# docker build -t jin/centos:6.7 . Sending build context to Docker daemon 37.38kB Step 1/9 : FROM centos:6.7 ---> 9f1de3c6ad53 Step 2/9 : MAINTAINER jin "jin@linux.com" ---> Using cache ---> 99d82b0eea4c Step 3/9 : RUN /bin/echo 'root:123456' |chpasswd ---> Using cache ---> ff3f33d1c001 Step 4/9 : RUN useradd jin ---> Running in 48c0cd93c3f5 Removing intermediate container 48c0cd93c3f5 ---> 2688337e172c Step 5/9 : RUN /bin/echo 'jin:123456' |chpasswd ---> Running in e7d7347850e9 Removing intermediate container e7d7347850e9 ---> 49bb06cc1843 Step 6/9 : RUN /bin/echo -e "LANG=\"en_US.UTF-8\"" >/etc/default/local ---> Running in c1ebc1a1b667 Removing intermediate container c1ebc1a1b667 ---> ee04f076fdc7 Step 7/9 : EXPOSE 22 ---> Running in c3e15517f0ec Removing intermediate container c3e15517f0ec ---> 3c3b68f5b66a Step 8/9 : EXPOSE 80 ---> Running in 46d8161a9bb1 Removing intermediate container 46d8161a9bb1 ---> 6487bc54a2b1 Step 9/9 : CMD /usr/sbin/sshd -D ---> Running in 3c4e2504f1a6 Removing intermediate container 3c4e2504f1a6 ---> 449e188f0215 Successfully built 449e188f0215 Successfully tagged jin/centos:6.7
其中,参数-t表示指定要建立的目标镜像名, .表示Dockerfile 文件所在目录,能够指定Dockerfile 的绝对路径。
[root@jin-10 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE jin/centos 6.7 449e188f0215 About a minute ago 191MB centos v2 e487a99a4de9 2 hours ago 314MB centos latest 67fa590cfc1c 5 days ago 202MB nginx latest 5a3221f0137b 10 days ago 126MB centos 6.7 9f1de3c6ad53 5 months ago 191MB hello-world latest fce289e99eb9 7 months ago 1.84kB training/webapp latest 6fae60ef3446 4 years ago 349MB
能够看到,ID449e188f0215的镜像就是咱们刚才用Dockerfile建立的。
咱们用新的镜像来建立容器:
[root@jin-10 ~]# docker run -i -t jin/centos:6.7 /bin/bash [root@b855cf5e62db /]# id jin uid=500(jin) gid=500(jin) groups=500(jin)
docker tag 命令,能够为镜像添加一个新的标签:
[root@jin-10 ~]# docker tag 449e188f0215 jin/centos:test [root@jin-10 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE jin/centos 6.7 449e188f0215 7 minutes ago 191MB jin/centos test 449e188f0215 7 minutes ago 191MB centos v2 e487a99a4de9 2 hours ago 314MB centos latest 67fa590cfc1c 5 days ago 202MB nginx latest 5a3221f0137b 10 days ago 126MB centos 6.7 9f1de3c6ad53 5 months ago 191MB hello-world latest fce289e99eb9 7 months ago 1.84kB training/webapp latest 6fae60ef3446 4 years ago 349MB
前面咱们实现了经过网络端口来访问运行在 docker 容器内的服务。下面咱们来实现经过端口链接到一个 docker 容器。
咱们建立一个 python 应用的容器:
[root@jin-10 ~]# docker run -d -P training/webapp python app.py d88408cc7cacfbeaaf26233135420c562db002c89e46637196c1f1ef6eff283e [root@jin-10 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d88408cc7cac training/webapp "python app.py" 6 seconds ago Up 4 seconds 0.0.0.0:32771->5000/tcp sad_kirch
咱们使用 -P 参数建立一个容器,使用 docker ps 能够看到容器端口 5000 绑定主机端口 32771。
咱们也可使用 -p 标识来指定容器端口绑定到主机端口。
两种方式的区别是:
[root@jin-10 ~]# docker run -d -p 5000:5000 training/webapp python app.py 30397628db6988d54e3304b24e7359949cca4b9cfbb3f4d69d4ebc11bb30bfcd [root@jin-10 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 30397628db69 training/webapp "python app.py" 10 seconds ago Up 1 second 0.0.0.0:5000->5000/tcp reverent_gould d88408cc7cac training/webapp "python app.py" 5 minutes ago Up 5 minutes 0.0.0.0:32771->5000/tcp sad_kirch
咱们能够指定容器绑定的网络地址,好比绑定 127.0.0.1:
[root@jin-10 ~]# docker run -d -p 127.0.0.1:5001:5000 training/webapp python app.py fc17fccfc477905897540347c0a99dcebfd97acd9831b87035bcd170c72b349d [root@jin-10 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES fc17fccfc477 training/webapp "python app.py" 14 seconds ago Up 6 seconds 127.0.0.1:5001->5000/tcp dreamy_greider 30397628db69 training/webapp "python app.py" About a minute ago Up About a minute 0.0.0.0:5000->5000/tcp reverent_gould d88408cc7cac training/webapp "python app.py" 7 minutes ago Up 7 minutes 0.0.0.0:32771->5000/tcp sad_kirch
上面的例子中,默认都是绑定 tcp 端口,若是要绑定 UDP 端口,能够在端口后面加上 /udp:
[root@jin-10 ~]# docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py a66ee68f9308940a38edf98f4b309c8995f7359e7a390e8c69a6825e4df317fb [root@jin-10 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a66ee68f9308 training/webapp "python app.py" 15 seconds ago Up 5 seconds 5000/tcp, 127.0.0.1:5000->5000/udp kind_shtern fc17fccfc477 training/webapp "python app.py" 16 minutes ago Up 16 minutes 127.0.0.1:5001->5000/tcp dreamy_greider 30397628db69 training/webapp "python app.py" 18 minutes ago Up 18 minutes 0.0.0.0:5000->5000/tcp reverent_gould d88408cc7cac training/webapp "python app.py" 23 minutes ago Up 23 minutes 0.0.0.0:32771->5000/tcp sad_kirch
docker port 命令可让咱们快捷地查看端口的绑定状况:
[root@jin-10 ~]# docker port kind_shtern 5000/udp -> 127.0.0.1:5000
端口映射并非惟一把 docker 链接到另外一个容器的方法。
docker 有一个链接系统容许将多个容器链接在一块儿,共享链接信息。
docker 链接会建立一个父子关系,其中父容器能够看到子容器的信息。
当咱们建立一个容器的时候,docker 会自动对它进行命名。另外,咱们也可使用 --name 标识来命名容器:
[root@jin-10 ~]# docker run -d -P --name jin training/webapp python app.py cdcb18044fecdf8098470b5461345e9f842e3607f55f2ffe4fea9a81f772bb38 [root@jin-10 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES cdcb18044fec training/webapp "python app.py" 11 seconds ago Up 3 seconds 0.0.0.0:32772->5000/tcp jin a66ee68f9308 training/webapp "python app.py" 5 minutes ago Up 4 minutes 5000/tcp, 127.0.0.1:5000->5000/udp kind_shtern fc17fccfc477 training/webapp "python app.py" 21 minutes ago Up 21 minutes 127.0.0.1:5001->5000/tcp dreamy_greider 30397628db69 training/webapp "python app.py" 23 minutes ago Up 23 minutes 0.0.0.0:5000->5000/tcp reverent_gould d88408cc7cac training/webapp "python app.py" 28 minutes ago Up 28 minutes 0.0.0.0:32771->5000/tcp sad_kirch
附:Docker命令大全:https://www.runoob.com/docker/docker-command-manual.html