Docker简单上手01

978 阅读4分钟

前言

之前也有听说过docker但是因为没有具体的业务接触所以并没有具体的去了解过,最近手头的工作也暂时没有那么急所以趁着时间来看下。

准备

系统:CentOS 7.6 64位

查看Linux核心版本,3.10版本及以上才可以安装docker

uname -r

更新yum包

yum update

查看docker是否曾经安装过

whereis docker

// 如果安装过,则删除之前的版本
yum remove docker docker-common docker-selinux docker-engine

安装需要的软件包

yum-util 提供yum-config-manager功能,另外两个是devicemapper驱动依赖的

yum install -y yum-utils device-mapper-persistent-data lvm2

设置yum源

yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

安装

默认安装最新版本

yum install docker-ce

安装某特定版本需增加版本号(如18.06.3.ce-3.el7)

yum install docker-ce-18.06.3.ce

配置用户

将 docker 的权限移交给非 root 用户,这样使用 docker 就不需要每次都 sudo 了:

sudo usermod -aG docker $USER

启动

systemctl start docker

注销用户或者重启之后就会生效。然后通过 systemd 服务配置 Docker 开机启动:

systemctl enable docker

验证安装是否成功

docker version

如果存在Client和Server则成功 安装成功

下载并安装 docker-compose

curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

配置并测试docker-compose

chmod +x /usr/local/bin/docker-compose

docker-compose version

成功图

配置镜像仓库

默认的镜像仓库 Docker Hub 在国外,国内拉取速度比较感人。建议参考这篇文章配置镜像加速

到这里前期的准备和环境安装工作就完成了,下面就开始上手实践吧!

上手实验

实例一:Hello World!

按照惯例,我们运行胰腺癌来自Docker的Hello World:

docker run hello-world

运行图

这个过程中Docker做了以下事情:

  • 检查本地是否有指定的 hello-world:latest 镜像(latest 是镜像标签,后面会细讲),如果没有,执行第 2 步,否则直接执行第 3 步。
  • 本地没有指定镜像(Unable to find xxx locally),从 Docker Hub 下载到本地。
  • 根据本地的 hello-world:latest 镜像创建一个新的容器并运行其中的程序。
  • 运行完毕后,容器退出,控制权返回给用户。

实例二:运行一个Nginx服务器

运行以下命令:

docker run -p 8080:80 nginx

Nginx运行图

运行之后,你会发现一直卡住,也没有任何输出,但放心你的电脑并没有死机。让我们打开浏览器访问localhost:8080(如果像我一样用的服务器可以打开服务器域名:8080来查看)

打开链接会看到Welecome to nginx!我们可以继续访问一些不存在的路由,比如localhost:8080/index,同样会提示404。这个时候我们运行

docker ps

可以看到Docker容器的输出,就有内容了。 总结下刚才Docker做的事情:

  • 检查本地是否有指定的 nginx:latest 镜像(关于 latest 标签,后面会细讲),如果没有,执行第 2 步,否则直接执行第 3 步。
  • 本地没有指定镜像(Unable to find xxx locally),从 Docker Hub 下载到本地。
  • 根据本地的 nginx:latest 镜像创建一个新的容器,并通过 **-p(--publish**)参数建立本机的 8080 端口与容器的 80 端口之间的映射,然后运行其中的程序。
  • Nginx 服务器程序保持运行,容器也不会退出。

实例三:后台运行Nginx

看上去很酷,不过像 Nginx 服务器这样的进程我们更希望把它抛到后台一直运行。按 Ctrl + C 退出当前的容器,然后再次运行以下命令:

docker run -p 8080:80 --name my-nginx -d nginx

注意到与之前不同的是,我们:

  • 加了一个参数 --name,用于指定容器名称为 my-nginx。
  • 加了一个选项 -d(--detach),表示 “后台运行”。

{% blockquote %} 容器的名称必须是唯一的,如果已经存在同一名称的容器(即使已经不再运行)就会创建失败。如果遇到这种情况,可以删除之前不需要的容器(后面会讲解怎么删除)。 {% endblockquote %}

Docker 会输出一串长长的 64 位容器 ID,然后把终端的控制权返回给了我们。我们试着访问 localhost:8080(服务器域名:8080),还能看到那一串熟悉的 Welcome to nginx!,说明服务器真的在后台运行起来了。

那我们怎么管理这个服务器呢?就像熟悉的 UNIX ps 命令一样,docker ps 命令可以让我们查看当前容器的状态:

docker ps

输出结果是这样的: ps输出

从这张表中,就可以清晰地看到了我们在后台运行的 Nginx 服务器容器的一些信息:

  • 容器 ID(Container ID)为 f104751ca7db(你机器上的可能不一样)。
  • 所用镜像(Image)为 nginx。
  • 运行命令 / 程序(Command)为 nginx -g 'daemon of...,这个是 Nginx 镜像自带的运行命令,暂时不用关心。
  • 创建时间(Created)为 an hour ago(一小时之前)。
  • 当前状态(Status)为 Up About an hout(已运行 超过一小时)。
  • 端口(Ports)为 0.0.0.0:8080->80/tcp,意思是访问本机的 0.0.0.0:8080 的所有请求会被转发到该容器的 TCP 80 端口。
  • 名称(Names)为刚才指定的 my-nginx。

如果我们要让容器停下来,通过 docker stop 命令指定容器名称或 ID 进行操作即可,命令如下:

docker stop my-nginx

实例四:交互式运行

运行以下命令,让我们进入到一个 Ubuntu 镜像中:

docker run -it --name dreamland ubuntu

可以看到我们加了 -it 选项,等于是同时指定 -i(--interactive,交互式模式)和 -t(--tty,分配一个模拟终端) 两个选项。以上命令的输出如下: ubuntu输出图

这时我们已经在这个Ubuntu镜像中了,可以运行一些命令来看一下

whoami

ls

按 Ctrl + D (或者输入 exit 命令)即可退出。你可以在 docker ps 的终端再次检查容器是否已经被关闭了。

销毁容器

我们刚才创建的 Docker 容器也只是用于初步探索,后续不会再用到。由于 Docker 容器是直接存储在我们本地硬盘上的,及时清理容器也能够让我们的硬盘压力小一些。我们可以通过以下命令查看所有容器(包括已经停止的):

docker ps -a

类似 Shell 中的 rm 命令,我们可以通过 docker rm 命令销毁容器,例如删除我们之前创建的 dreamland 容器:

docker rm dreamland
# 或者指定容器 ID,记得替换成自己机器上的
# docker rm f104751ca7db(你机器上的可能不一样)。

但如果我们想要销毁所有容器怎么办?一次次输入 docker rm 删除显然不方便,可以通过以下命令轻松删除所有容器:

docker rm $(docker ps -aq)

docker ps -aq 会输出所有容器的 ID,然后作为参数传给 docker rm 命令,就可以根据 ID 删除所有容器啦。

删除运行中的容器

docker rm -f dreamland

同样的,我们可以删除所有容器,无论处于什么状态:

docker rm -f $(docker ps -aq)

容器化第一个应用:开启筑梦之旅

在之前的步骤中,我们体验了别人为我们提前准备好的镜像(例如 hello-world、nginx 和 ubuntu),这些镜像都可以在 Docker Hub 镜像仓库中找到。在这一步,我们将开始筑梦之旅:学习如何容器化(Containerization)你的应用。

运行以下命令来获取代码,然后进入项目:

git clone -b start-point https://github.com/tuture-dev/docker-dream.git
cd docker-dream

如果没有安装git,可以运行

yum install git

来安装,也可以到GIT官网来查看如何安装你所对应的平台。

在这一步中,我们将容器化这个用 React 编写的前端应用,用 Nginx 来提供前端页面的访问。

什么是容器化

什么是容器化:

  • 编写代码:我们已经提供了写好的代码。
  • 构建镜像。
  • 创建和运行容器:通过容器的方式运行我们的应用。

构建镜像

构建 Docker 镜像主要包括两种方式:

  • 手动:根据现有的镜像创建并运行一个容器,进入其中进行修改,然后运行 docker commit 命令根据修改后的容器创建新的镜像。
  • 自动:创建 Dockerfile 文件,指定构建镜像的命令,然后通过 docker build 命令直接创建镜像。

准备工作

我们先把前端项目 client 构建成一个静态页面。确保你的机器上已经安装 Node 和 npm(点击这里下载,或使用 nvm),然后进入到 client 目录下,安装所有依赖,并构建项目:

cd client
npm install
npm run build

如果安装node和npm出现问题的可以看下我之前的这篇文章Linux安装Node

等待一阵子后,你应该可以看到 client/build 目录,存放了我们要展示的前端静态页面。

创建 Nginx 配置文件 client/config/nginx.conf,代码如下:

server {
    listen 80;
    root /www;
    index index.html;
    sendfile on;
    sendfile_max_chunk 1M;
    tcp_nopush on;
    gzip_static on;

    location / {
        try_files $uri $uri/ /index.html;
    }
}

上面的配置大致意思是:监听 80 端口,网页根目录在 /www,首页文件是 index.html,如果访问 / 则提供文件 index.html。

创建 Dockerfile

然后就是这一步骤中最重要的代码:Dockerfile!创建 client/Dockerfile 文件,代码如下:

FROM nginx:1.13

# 删除 Nginx 的默认配置
RUN rm /etc/nginx/conf.d/default.conf

# 添加自定义 Nginx 配置
COPY config/nginx.conf /etc/nginx/conf.d/

# 将前端静态文件拷贝到容器的 /www 目录下
COPY build /www

可以看到我们用了 Dockerfile 中的三个指令:

  • FROM 用于指定基础镜像,这里我们基于 nginx:1.13 镜像作为构建的起点。
  • RUN 命令用于在容器内运行任何命令(当然前提是命令必须存在)。
  • COPY 命令用于从 Dockerfile 所在的目录拷贝文件到容器指定的路径。

现在可以来构建我们的镜像了,运行以下命令:

# 如果你已经在 client 目录中
#(注意最后面有个点,代表当前目录)
docker build -t dream-client .

# 如果你回到了项目根目录
docker build -t dream-client client

可以看到我们指定了 -t(--tag,容器标签)为 dream-client,最后指定了构建容器的上下文目录(也就是 当前目录 . 或 client)。

运行以上的命令之后,你会发现:

Sending build context to Docker daemon  289.4MB

接着运行了一系列的 Step(4 个),然后提示镜像构建成功。

为什么这个构建上下文(Build Context)这么大?因为我们把比 “黑洞” 还 “重” 的 node_modules 也加进去了!(忍不住想起了下面这张图) 构建

Docker 提供了类似 .gitignore 的机制,让我们可以在构建镜像时忽略特定的文件或目录。创建 client/.dockerignore 文件(注意 dockerignore 前面有一个点):

node_modules

再次运行构建命令:

docker build -t dream-client .

再次构建构建 可以看到这次只有1.217MB,而且速度也明显快了很多.

运行容器

终于到了容器化的最后一步 —— 创建并运行我们的容器!通过以下命令运行刚才创建的 dream-client 镜像:

docker run -p 8080:80 --name client -d dream-client

与之前类似,我们还是设定端口映射规则为 8080:80,容器名称为 client,并且通过 -d 设置为后台运行。然后访问 localhost:8080(老样子--服务器域名:8080): 运行容器 可以看到如图所示的页面,表示容器运行成功.

关于镜像标签

在刚才的实战中,你也许已经注意到在拉取和构建镜像时,Docker 总是会为我们加上一个 :latest 标签,这个 :latest 的含义便是 “最新” 的意思。和软件的版本机制一样,镜像也可以通过标签实现 “版本化”。

实际上,我们完全可以在拉取或构建镜像时指定标签(通常被认为是一种好的做法):

docker pull nginx:1.13
docker build -t dream-client:1.0.0

还可以给现有的镜像打上标签:


# 把默认的 latest 镜像打上一个 newest 标签
docker tag dream-client dream-client:newest
# 甚至可以同时修改镜像的名称和标签
docker tag dream-client:1.0.0 dream-client2:latest

可以看到,标签未必一定是版本,还可以是任何字符串(当然最好要有意义,否则过了一阵子你也不记得这个打了这个标签的容器有什么作用了)。

关于 Dockerfile

Dockerfile 实际上是默认名称,我们当然可以取一个别的名字,例如 myDockerfile,然后在构建镜像时指定 -f(--file)参数即可:

docker build -f myDockerfile -t dream-client .

这里举两个经典的使用场景:

  • 例如在 Web 开发时,分别创建 Dockerfile.dev 用于构建开发镜像,创建 Dockerfile.prod 构建生产环境下的镜像;
  • 在训练 AI 模型时,创建 Dockerfile.cpu 用于构建用 CPU 训练的镜像,创建 Dockerfile.gpu 构建用 GPU 训练的镜像。

最后

这篇文章是我跟着图灵社区的流程走了一遍所记录的过程,点击这里查看图灵社区