前端 Docker 基本教程

为什么要学习 Docker ?

每学一个东西,我们肯定是基于某个需求去学习的,众所周知,软件开发最麻烦的是环境配置,开发好好的,部署出问题就很难受,所以为了确保开发、测试、部署环境一致,且高效的部署所以选择了容器技术而非 VM ,而 Docker 是基于 Linux 容器技术的开源项目,它的口头禅就是:“一次构建,处处运行”,具有轻量,速度,社区活跃,且拓展性高

安装

点我进入官网安装
Docker 支持 Linux、Mac、 Window,直接去官网下载安装就行了

快速开始

学习新的技术都需要一个 Hello World,让我们快速开始体验一下 Docker
直接进入终端开始吧!

# 拉取nginx镜像
docker pull nginx
# 创建一个nginx容器
docker run -d --name test-nginx -p 3000:80 nginx


然后打开 localhost:3000 即可访问到熟悉的 nginx 页面了

是不是非常简单?那我们接下来具体说一说 Docker 的组成

镜像 image

镜像是一个二进制文件,里面具有应用程序以及依赖,只有通过它,Docker 才能够生成容器,相当于模具一样,同一个镜像文件可以生成多个容器实例

对于如何制作镜像,一般来说我们都是通过加工别人基础镜像来生成我们自己的镜像,而不是从零开始,而且我们也可以在这里共享我们的镜像,这也是我们选择它的理由之一,我们可以享受社区的贡献

镜像常用的命令

# 列出本机的所有 image 文件。
$ docker image ls
# 拉取镜像
$ docker pull [imageName]
# 删除 image 文件
$ docker image rm [imageName]

用 Dockerfile 构建一个镜像

在前面我们已经使用过nginx的镜像了,这次我们尝试用 Dockerfile 构建一个自己的镜像
新建一个 docker-test 文件夹,在里面新建一个index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Hello World</title>
  </head>
  <body>
    <h1>Hello World!</h1>
  </body>
</html>

然后新建一个 Dockerfile 文件

# 声明基于 nginx 最新的镜像 这里说一下镜像名:后面的是标签 默认是latest
FROM nginx:latest
# 把刚才 index.html 复制到 nginx 的 html 路径去
COPY index.html /usr/share/nginx/html/index.html
# 声明暴露80端口
EXPOSE 80

运行命令

#  生成一个名为 nginx 标签为0.0.1 的镜像 ,注意最后还有一个 .
docker image build -t nginx:0.0.1 .
# 根据刚生成的镜像 启动容器
docker run -d --name test-nginx1 -p 3001:80 nginx:0.0.1

这时候再次访问 locahost:3001 已经不是默认的 nginx 的访问页面了
这里解释一下参数

  • -p 参数是指容器的 80 端口映射到本机的 3001 端口
  • -d 守护式运行(适合运行应用程序和服务)
  • --name  容器名称 如果不指定则是一个随机的名称

容器 container

容器常用的命令

# 查看正在运行的容器
docker ps
# 查看所有创建过的容器(运行或者关闭)
docker ps -a
# 停止容器
docker stop [container]
# 启动容器
docker start [container]
# 删除容器
docker rm [container]
# 查看后台运行的日志
docker logs [containe]

可以先用这些容器命令操作一下我们之前创建的容器,尝试一下
那么在上一节我们自己构建了一个镜像代替了 nginx 的默认页面,那如果我们还想改怎么办?除了新构建一个镜像之外,我们还可以直接进入容器里进行修改

docker container exec -it [containe] /bin/bash

这样就进去了容器的 shell ,可以随意进行操作,当然就算你误操作比如运行了经典的了,也没有关系
在这里我们是使用了 -it 这个参数 它和 -d 区别就在于
-d => 使用 pm2  start index.js
-it => 使用 node.js
当然,真正开发的时候,肯定不可能是这样去修改了,好比之前的端口映射,也可以将容器的内部的目录也映射出来实现共共享,这就是接下来要说的 Volume

数据卷 Volume

回到我们 docker-test 文件夹,然后重新启动一个nginx容器(这里使用的端口和容器名与快速开始的创建的容器相同,请同学们复习一下容器命令先自行删除再创建)

docker run -d --name test-nginx -v $PWD/index.html:/usr/share/nginx/html/index.html -p 3000:80  nginx

我们打开 locahost:3000 修改一下 index.html 的内容为 Hello Volume ,刷新一下网页即可看到我们修改的内容
在这里
很容易发现我们和之前的区别就是使用了 -v参数  本地路径:容器路径 通过这样进行映射,这样当我们修改本地的文件的时候就等于修改了容器内的文件
那么就当在一个项目中,nginx部署好了前端,那么我们需要一个服务提供数据,在 docker-test 的文件夹下面
创建一个 mysql 文件夹 在mysql文件夹中创建一个data存储数据,创建一个my.cnf用作配置

[mysqld]
user=mysql
character-set-server=utf8
default_authentication_plugin=mysql_native_password
secure_file_priv=/var/lib/mysql
expire_logs_days=7
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
max_connections=1000
 
[client]
default-character-set=utf8
 
[mysql]
default-character-set=utf8

启动容器

docker run --name test-mysql -it -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -v $PWD/mysql/my.cnf:/etc/mysql/my.cnf -v $PWD/mysql/data:/var/lib/mysql -d mysql

然后我们通过上一节学会的命令进入 test-mysql 容器中创建数据库以及创建表 加插入一条数据

docker container exec -it test-mysql /bin/bash
# 下面是 test-mysql 容器中的 shell
# 登陆 输入密码
mysql -u root -p 
# 创建数据库 test
create databse test;
# 进入 test 数据库
use test;
# 进入 PEOPLE 数据表 字段为 name  age
Create Table PEOPLE (name VARCHAR(20), age CHAR(20));
# 插入一行数据到 PEOPLE
Insert into PEOPLE Values('kdq', '24')

然后我们退出容器,再 docker-test 下创建一个文件夹 node ,并创建一个 index.js 文件

const http = require("http");
const mysql = require("mysql");
const connection = mysql.createConnection({
  host: "test-mysql",
  user: "root",
  password: "root",
  database: "test"
});
connection.connect();

const server = http.createServer().listen(3001);

server.on("request", (req, res) => {
  if (/testapi/.test(req.url)) {
    try {
      var sqlstr = "Select * From PEOPLE";
      connection.query(sqlstr, function(err, result) {
        if (err) {
          console.log("SELECT ", err.message);
          return;
        }
        res.end(JSON.stringify(result));
      });
    } catch (error) {
      res.end("404 not found");
    }
  } else {
    res.end("404 not found");
  }
});

然后启动容器

docker run -it --name test-node -v $PWD/node:/var/www/node  -v $PWD/mysql/data:/var/lib/mysql -p 3001:3001 node /bin/bash
# 下面是 test-node 容器中的 shell
cd /var/www/node
node index.js

我们发现 mysql 的操作报错了 connect ECONNREFUSED 127.0.0.1:3306 ,原来是因为我们的 mysql 和 node 是两个容器,而容器是相互隔离的,无法 ping 通

那么难道我们得把 mysql 和 node 都得部署在一个容器里?其实 Docker 更建议一个容器做一件事情,而这种理念其实在我们的开发中也是随处可见的,所以 Docker 可以使用 Networking 进行通信

网络 Networking

首先创建一个网络

docker network create test-net

然后把上一节启动 test-mysql 和 test-node 的容器的命令改成

# test-mysql
docker run --name test-mysql -it -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -v $PWD/mysql:/etc/mysql --network test-net -d mysql
# test-node
docker run -it --name test-node -v $PWD/node:/var/www/node --network test-net -p 3001:3001 node /bin/bash

这时候我们在 node 的 index.js 中修改一下连接 mysql 的 host

const connection = mysql.createConnection({
  host: "test-mysql",
  user: "root",
  password: "root",
  database: "test" 
});

然后我们启动一下 node 服务 访问 localhost:3001/testapi 就能看到我们查询到的数据了
那么我们也可以将 nginx 加入 test-net 网络中互相通信,具体就留给你们自己去做了

组合 docker-compose

经过上一节我们发现启动容器要输入这么多参数,而且多个容器服务就要启动多次,不仅繁琐,还容易出错
我们可以写 Dockerfile 写一层层命令来构建镜像,是不是也可以用一个配置去启动容器?
答案是可以的,这时候就需要 docker-compose ,当然,如果你的 docker 安装的时候自带就不用再次安装了,具体可以观看文档 点我下载
安装之后 在我们的 docker-test 文件夹下新建一个 docker-compose.yml

version: "3.7"
services:
  test-mysql:
    image: mysql
    volumes:
      - ./mysql/my.cnf:/etc/mysql/my.cnf
      - ./mysql/data:/var/lib/mysql
    ports:
      - 3306:3306
    environment:
      - MYSQL_ROOT_PASSWORD=root
    networks:
      - test-net
  test-node:
    image: node
    volumes:
      - ./node:/var/www/node
    ports:
      - 3001:3001
    command:
      - /bin/bash
      - -c
      - |
        cd /var/www/node
        node index.js
        tail -f /dev/null
    networks:
      - test-net
    depends_on:
      - test-mysql
  test-nginx:
    image: nginx
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./nginx/index.html:/usr/share/nginx/html/index.html
    ports:
      - 3000:80
    networks:
      - test-net
    depends_on:
      - test-node
networks:
  test-net:
    driver: bridge

目前的 docker-test 情况

|-- mysql
    |-- data
    |-- my.cnf
|-- nginx
    |-- index.html
    |-- nginx.conf
|-- node
    |-- node_modules 
    |-- index.js
    |-- package.json
    |-- package-lock.json
|-- docker-compose.yml

通过 docker-compose 启动容器(先把之前启动的三个容器关了)

docker-compose up -d

打开 localhost:3001/testapi 发现依然查询到了数据,就这样一个简单的项目环境准备好了

总结

简单的介绍一下如何使用Docker以及基本的命令,相信大家已经对 Docker 有所了解,对于相关配置想知道更多的可以查看官网文档,如果想看书的同学,可以看第一本Docker书

posted @ 2020-02-27 00:40  云剪者  阅读(222)  评论(1编辑  收藏