没有人不爱惜他的生命,但不多人珍视他的时间。 —— 梁实秋php
Docker 自 2013 年发布至今一直备受关注,从招聘面试角度来看有些职位对于了解 Docker、K8S 这些也有一些加分项,同时学习 Docker 也是后续学习 K8S 的基础,可是对于 Docker 不少人也需并不了解,其实 Docker 也并无那么难,本文从 Docker 入门到应用实践为你们进行讲解,中间也列举了不少实例,但愿能帮助你们更好的理解。html
做者简介:五月君,Nodejs Developer,热爱技术、喜欢分享的 90 后青年,公众号「Nodejs技术栈」,Github 开源项目 www.nodejs.rednode
本篇 Docker 入门到实践路线图以下所示mysql
Docker 能够将应用以集装箱的方式进行打包,经过镜像的方式能够实如今不一样的环境下进行快速部署,在团队中还可实现一次打包,屡次共享,使用 Docker 能够轻松的为任何应用建立一个轻量级的、可移植的、自给自足的容器。linux
例如,咱们在本地将编译测试经过的程序打包成镜像,能够快速的在服务器环境中进行部署,有时也能解决不一样的开发环境形成的问题 “明明我本地是好的,可是一到服务器就不行”。nginx
为何要使用 Docker?总结下来其有如下优势:git
中间部位为咱们进行 Docker 操做的宿主机,其运行了一个 Docker daemon 的核心守护程序,负责构建、运行和分发 Docker 容器。github
左边为 Docker 客户端,其与 Docker 守护进程进行通讯,客户端会将 build、pull、run 命令发送到 Docker 守护进程进行执行。web
右边为 Docler 注册表存储 Docker 镜像,是一个全部 Docker 用户共享 Docker 镜像的服务,Docker daemon 与之进行交互。面试
参考 docs.docker.com/engine/dock…
什么是 Docker 镜像
Docker 会把应用程序及依赖打包进镜像(Images)里,提供了容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等),经过这个镜像文件可生成 Docker 容器。
例如:这个镜像文件包含了一个完整的 Ubuntu 系统,咱们能够在 Ubuntu 镜像基础之上安装了 Redis、Mysql 等其它应用程序,能够回顾下 Docker 架构一瞥 在 DOCKER_HOST 里面有个 images。
另外在制做好镜像文件以后能够拷贝到其它机器使用,它是通用的,镜像的制做能够基于 Dockerfile 构建后面会讲解。
什么是 Docker 容器
容器是镜像的可运行实例,你可使用 Docker API 建立、启动、中止、移动或删除它,
在默认状况下,容器与其它容器及其主机是隔离的,拥有本身的独立进程空间、网络配置。
容器由其镜像以及在建立或启动容器时提供的任何配置选项定义。当容器被删除时,对其状态的任何未存储在持久存储中的更改都会消失。
Docker 是一个开源的商业产品,提供了社区版(CE)和企业版(EE),如下也都是基于企业版进行介绍,我这里操做系统采用的 Linux 下 Ubuntu 系统,更多安装方式也可参照官网安装指南 docs.docker.com/install/
这个看状况,由于 Docker 的源在国外,国内访问速度可能会不稳定,有须要的能够按照如下步骤更换为国内源
$ sudo vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://registry.docker-cn.com"]
}
复制代码
$ sudo service docker restart
复制代码
sudo apt-get update
复制代码
$ sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
复制代码
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
复制代码
$ sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable"
复制代码
sudo apt-get update
复制代码
sudo apt-get install docker-ce docker-ce-cli containerd.io
复制代码
执行如下命令使用脚本自动安装,这也是最简化的安装流程,它会检测你当前使用的 Linux 版本,选择合适的安装包进行安装,
sudo wget -qO- https://get.docker.com | sh
复制代码
因为 Docker 操做须要拥有 root 权限,为避免每次都输入 sudo,能够把用户加入 Docker 用户组,执行如下命令
# https://docs.docker.com/install/linux/linux-postinstall/#manage-docker-as-a-non-root-user
$ sudo usermod -aG docker $USER
复制代码
安装完成后,运行下面的命令,验证是否安装成功
$ docker -v
Docker version 19.03.2, build 6a30dfc
复制代码
上面对 Docker 的镜像和容器作了简要概述,有个初步的了解以后,再来看下 Docker 镜像和容器的实践。
hello-world 为镜像名字,docker image pull 为抓取镜像命令,Docker 官方提供的 image 文件都放在 library 默认组里,library/hello-world 也就为 image 文件的位置。
$ docker image pull hello-world
# 如下为抓取过程当中的日志信息
Using default tag: latest
latest: Pulling from library/hello-world
1b930d010525: Pull complete
Digest: sha256:451ce787d12369c5df2a32c85e5a03d52cbcef6eb3586dd03075f3034f10adcd
Status: Downloaded newer image for hello-world:latest
docker.io/library/hello-world:latest
复制代码
image 文件抓取成功经过 docker images 或 docker image ls 命令查看当前都有哪些镜像
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest fce289e99eb9 8 months ago 1.84kB
复制代码
执行 docker container run
命令会生成一个正在运行的容器实例,另外 docker container run
发现本地没有指定的 image 文件,其自身还有自动抓取 image 文件功能,就是上面讲解的 docker image pull
命令
$ docker container run hello-world
Hello from Docker!
# 如下内容省略
...
复制代码
使用 docker ps
或 docker container ls
命令用来查看正在运行的容器列表,这个时候是没有正在运行的容器实例的,由于在以上 docker container run hello-world
命令执行以后 hello-world
就会中止,容器也会随着自动中止,但并非全部的容器运行以后也都会中止的,例如 Nginx 后面会进行实践。
$ docker ps
复制代码
经过 docker ps --all
或 docker container ls --all
命令能够查看全部的容器实例,包含已经中止的
$ docker ps --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a662ec198a83 hello-world "/hello" 10 minutes ago Exited (0) 10 minutes ago exciting_wing
复制代码
如下命令会用 nginx 镜像启动一个容器,命名为 nginxserver,并映射到 8081 端口
$ docker container run --name nginxserver -d -p 8081:80 nginx
复制代码
好了,咱们如今就可使用 http://localhost:8081/ 来访问这个 Nginx 服务器,因为我这里是在虚拟机上安装的 Docker 所以要使用个人虚拟机地址 http://192.168.6.128:8081/ 进行访问,一样若是你是在虚拟机、云服务器上安装的 Docker 也要使用相应的 ip 来访问,若是是在本机直接 localhost 就能够。如下为 Nginx 默认的欢迎页面。
再分别看下目前的 image 列表和正在运行的容器
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 5a3221f0137b 3 weeks ago 126MB
hello-world latest fce289e99eb9 8 months ago 1.84kB
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b7bf26745b3f nginx "nginx -g 'daemon of…" 23 minutes ago Up 23 minutes 0.0.0.0:8081->80/tcp nginxserver
复制代码
经过 docker container kill [containID]
命令终止正在运行的容器
# docker container kill [containID]
$ docker container kill b7bf26745b3f
复制代码
上面的终止容器并不会删除容器文件,仅仅是容器中止运行,经过 docker ps --all 命令查看全部的容器列表
$ docker ps --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b7bf26745b3f nginx "nginx -g 'daemon of…" 29 minutes ago Exited (137) About a minute ago nginxserver
a662ec198a83 hello-world "/hello" 49 minutes ago Exited (0) 49 minutes ago exciting_wing
复制代码
因为已经终止容器文件依然会占据着咱们的磁盘空间,在不使用的状况可经过 docker container rm [containerID]
命令删除
$ docker container rm b7bf26745b3f a662ec198a83
复制代码
执行以上命令以后,再使用 docker ps --all
命令,此时容器列表就为空了。
一样删除一个镜像文件也很简单执行 docker rmi [imageID]
命令便可
$ docker rmi 5a3221f0137b fce289e99eb9
复制代码
Dockerfile 是由一系列的参数、命令构成的可执行脚本,用来构建、定制 Docker 镜像。本节经过一个 Node.js 的简单项目为例,介绍下如何编写 Dockerfile 文件、如何在 Docker 容器里运行 Node.js 项目。
/usr/src/nodejs/hello-docker 目录下新建 app.js
// /usr/src/nodejs/hello-docker/app.js
const http = require('http');
const PORT = 30010;
const server = http.createServer((req, res) => {
res.end('Hello Docker');
})
server.listen(PORT, () => {
console.log('Running on http://localhost:', PORT);
});
复制代码
/usr/src/nodejs/hello-docker 目录下新建 package.json
// /usr/src/nodejs/hello-docker/package.json
{
"name": "hello-docker",
"version": "1.0.0",
"description": "",
"author": "May",
"main": "app.js",
"scripts": {
"start": "node app.js"
},
"dependencies": {
}
}
复制代码
首先在项目根目录下建立 .dockerignore 文件,把不须要打包进 Docker Image 里的文件进行过滤
# /usr/src/nodejs/hello-docker/.dockerignore
.git
node_modules
复制代码
Dockerfile
项目根目录下新建 Dockerfile 文件
# /usr/src/nodejs/hello-docker/Dockerfile
FROM node:10.0
# 在容器中建立一个目录
RUN mkdir -p /usr/src/nodejs/
# 定位到容器的工做目录
WORKDIR /usr/src/nodejs/
# RUN/COPY 是分层的,package.json 提早,只要没修改,就不会从新安装包
COPY package.json /usr/src/app/package.json RUN cd /usr/src/app/ RUN npm i
# 把当前目录下的全部文件拷贝到 Image 的 /usr/src/nodejs/ 目录下
COPY . /usr/src/nodejs/
EXPOSE 30010
CMD npm start 复制代码
Dockerfile 文件建立好以后,使用 docker image build
命令建立镜像文件,-t 参数用来指定镜像的文件名称,最后一个 . 也不要省略,表示 Dockerfile 文件的所在目录
$ docker image build -t hello-docker .
复制代码
执行以上命令以后,咱们来查看下新生成的镜像文件 hello-docker
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-docker latest 6b1c2775591e 4 minutes ago 675MB
node 10.0 1c1272350058 16 months ago 675MB
复制代码
镜像构建成功以后经过 docker container run 命令来生成一个容器,几个参数说明:
$ docker container run -d -p 30000:30010 hello-docker
复制代码
执行以上命令以后经过 docker ps 查看咱们刚刚运行的容器信息
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c2891d477edf hello-docker "/bin/sh -c 'npm sta…" 15 seconds ago Up 14 seconds 0.0.0.0:30000->30010/tcp pedantic_mestorf
复制代码
不出什么意外,此时咱们的 Node.js 服务已经运行在 Docker 容器的虚拟环境里了,访问 curl http://localhost:30000
能够进行测试。
$ curl http://localhost:30000
Hello Docker
复制代码
查看运行日志,“c2891d477edf” 为容器 ID
$ docker logs -f c2891d477edf
> hello-docker@1.0.0 start /usr/src/nodejs/hello-docker
> node app.js
Running on http://localhost: 30010
复制代码
为了方便排查内部容器文件,能够经过 docker exec -it c2891d477edf /bin/sh 命令进入容器,c2891d477edf 为容器 ID
$ docker exec -it c2891d477edf /bin/sh
$ ls # 列出目录列表
Dockerfile app.js package-lock.json package.json
复制代码
因为咱们已经启动了 hello-docker 这个服务,在容器里再次操做 node app.js 就会报端口冲突
$ node app
events.js:167
throw er; // Unhandled 'error' event
^
Error: listen EADDRINUSE :::30010
复制代码
按下 Ctrl + d (或者输入 exit)退出容器
Registry 是一个注册服务器,是一个集中存放镜像仓库的地方,这里着重介绍下 Docker Hub,它是官方维护的一个公共仓库,咱们的大部分需求也均可从这里下载。
在开始以前你须要先去 Docker 官网注册一个帐号 hub.docker.com/ 后续讲解发布镜像须要用到
使用 docker search 镜像名称
能够搜索你须要的镜像,搜索结果会根据 STARS 进行排序
$ docker search nginx
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
nginx Official build of Nginx. 11935 [OK]
jwilder/nginx-proxy Automated Nginx reverse proxy for docker con… 1651 [OK]
richarvey/nginx-php-fpm Container running Nginx + PHP-FPM capable of… 740 [OK]
...
复制代码
搜索到须要的镜像后执行 docker pull 命令拉取镜像
$ docker pull nginx
复制代码
$ docker login
复制代码
# docker image tag [imageName] [username]/[repository]:[tag]
$ docker image tag hello-docker mayjun/hello-docker
复制代码
# docker image push [username]/[repository]:[tag]
$ docker image push mayjun/hello-docker
复制代码
镜像发布成功以后,在本身的我的用户下也能够看到镜像信息
若是你想在别的机器上也使用这个镜像,直接 docker pull 拉取便可,实现镜像的共享。
Compose 是 Docker 官方开源的一个项目,能够管理多个 Docker 容器组成一个应用,例如 Web 服务,除了服务自己还有数据库、Redis、Nginx 等一系列相关联服务须要安装。
有个 Compose 的支持,咱们只须要定义一个 YAML 格式的配置文件(docker-compose.yml
),来编写一个项目所须要的多个容器配置及调用关系,经过简单的命令便可同时开始或者关闭这些容器。
# compose 下载以后经过管道的方式输入至 /usr/local/bin/docker-compose
# uname -s 查找是什么系统,例如:Linux
# uname -m 查找是什么版本,例如:x86_64
$ curl -L https://github.com/docker/compose/releases/download/1.25.0-rc2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
# 把这个文件变成可执行的
$ chmod +x /usr/local/bin/docker-compose
复制代码
查看安装是否成功
$ docker-compose --version
docker-compose version 1.25.0-rc2, build 661ac20e
复制代码
WordPress 是一个免费开源的我的博客系统,使用的也是比较多的,而且也有 Docker 镜像,使用 Docker 部署仍是很是简单的。
在 /usr/src/wordpress 目录下,创建 docker-compose.yml 配置文件,写入以下内容:
mysql:
image: mysql:5.7
environment:
- MYSQL_ROOT_PASSWORD=123456
- MYSQL_DATABASE=wordpress
web:
image: wordpress
links:
- mysql
environment:
- WORDPRESS_DB_PASSWORD=123456
ports:
- "192.168.6.128:8080:80"
working_dir: /var/www/html
volumes:
- wordpress:/var/www/html
复制代码
启动容器,浏览器输入 http://192.168.6.128:8080 便可看到效果,能够亲自实践下
# -d 参数表示后台启动
$ docker-compose up -d
复制代码
关闭容器,执行如下命令须要在 docker-compose.yml 配置文件同级目录下
$ docker-compose stop
复制代码
本文是做者 “五月君” 在实践 Docker 过程当中的一些知识总结,刚开始也是从零开始的,若是你想学习 Docker 不知道该如何入手,能够参考本文,后续还会有 Docker 在应用程序中的实践分享,感兴趣的能够关注公众号 “Nodejs技术栈” Github: github.com/Q-Angelo/No… 获取最新消息