本文是我经过三个星期业余时间学习后而写的文章,对docker的了解还处于入门阶段。但愿本文能帮忙一些想学习docker的朋友快速入门。练习及实战代码都在github仓库中。若是个人文章能帮助到你的话,能够给个人docker项目点个赞哦javascript
本次实战案例是todolist。技术栈为vue、node、mysql。具体代码见项目目录todolist,下面就不一一贴代码了。就讲下重点。html
下面我就顺着依赖关系来说,因此先从mysql开始讲起vue
执行:docker run --name mymysql -d -p 3308:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql
java
在执行该语句以前,假如你以前没有pull过mysql镜像。docker在本地找不到你要的镜像就会帮你从docker仓库拉取mysql:latest镜像。node
这个时候容器就启动成功了。mysql
尝试下用navicat链接下试试git
鼠标放入黄色小三角出现以下报错。github
2013 - Lost connection to MySQL server at 'reading initial communication packet', system error: 0 "Internal error/check (Not system error)"
这是由于mysql8以上,都会使用新的验证方式。sql
不妨查下信息: select host,user,plugin,authentication_string from mysql.user;
vue-cli
mysql> select host,user,plugin,authentication_string from mysql.user; +-----------+------------------+-----------------------+------------------------------------------------------------------------+ | host | user | plugin | authentication_string | +-----------+------------------+-----------------------+------------------------------------------------------------------------+ | % | root | caching_sha2_password | *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9 | | localhost | mysql.infoschema | caching_sha2_password | $A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED | | localhost | mysql.session | caching_sha2_password | $A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED | | localhost | mysql.sys | caching_sha2_password | $A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED | )7k44VulAglQJgGpvgSG.ylA/rdbkqWjiqQJiq3DGsug5HIy3 |ord | $A$005$0pU+sGm[on +-----------+------------------+-----------------------+------------------------------------------------------------------------+
plugin一栏可看到都是caching_sha2_password。
那么如何才能将其改为可链接的呢?只须要将其plugin改为mysql_native_password就能够访问了。
ALTER user 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
你能够先用上面查询帐户信息查下是否修改为功了。
修改为功后,能够尝试下用navicat链接下mysql。不出意外的话就能成功链接上了。
固然我下面的例子用mysql:5.6,方便操做,不须要修改plugin。
执行命令:docker run --name mymysql -d -e MYSQL_ROOT_PASSWORD=123456 -p 3308:3306 mysql:5.6
启动容器后能够执行:docker exec -it mymysql bash
进入容器
执行:mysql -uroot -p123456
进入mysql控制台
执行:show databases;
查看mysql数据库
mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | +--------------------+ 3 rows in set (0.00 sec)
执行:create database todolist;
建立todolist应用的数据库
执行:show databases;
查看刚刚建立的todolist数据库
mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | todolist | +--------------------+ 4 rows in set (0.00 sec)
能够看到数据库中多了个todolist数据库
接下来选择该todolist数据库
执行:use todolist;
选中该数据库
建立表:
CREATE TABLE list ( id INT(11) AUTO_INCREMENT PRIMARY KEY, text VARCHAR(255), checked INT(11) DEFAULT 0 );
执行:show tables;
查看todolist数据库下的表
mysql> show tables; +--------------------+ | Tables_in_todolist | +--------------------+ | list | +--------------------+ 1 row in set (0.00 sec)
执行:describe list;
查看表
mysql> describe list; +---------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +---------+--------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | text | varchar(255) | YES | | NULL | | | checked | int(11) | YES | | 0 | | +---------+--------------+------+-----+---------+----------------+ 3 rows in set (0.01 sec)
执行:insert into list set checked = 0, text = 'haha';
往表中插入一条数据;
执行:select * from list;
mysql> select * from list; +----+------+---------+ | id | text | checked | +----+------+---------+ | 1 | haha | 0 | +----+------+---------+ 1 row in set (0.01 sec)
一切正常
mysql服务启动好了,接下来就是启动node服务,并链接刚启动的mysql服务了。
话很少说,直接上代码,解释看注释
// index.js const mysql = require('mysql'); // mysql包 const express = require('express'); const app = express(); const bodyParser = require('body-parser'); // post请求须要引入的包 app.use(bodyParser.json()); // mysql配置(用于链接刚启动的mysql服务) const opt = { host: 'localhost', user: 'root', port: '3308', password: '123456', database: 'todolist' }; const connection = mysql.createConnection(opt); const sqlFn = (sql) => { return new Promise((resolve, reject) => { connection.query(sql, (err, results, filelds) => { if (err) throw err; resolve(results); }); }) } connection.connect(async (err) => { if (err) throw err; console.log('mysql connncted success!'); }) // todolist 列表查询 app.get('/getList', async (req, res) => { const sql = `SELECT * FROM list`; const data = await sqlFn(sql); res.json({ code: 0, data, message: 'success' }) }) // todolist 插入数据 app.post('/insert', async (req, res) => { const sql = `INSERT INTO list SET checked = ${req.body.checked}, text = '${req.body.text}'`; const data = await sqlFn(sql); res.json({ code: 0, data, message: 'success' }) }) app.listen(3000);
执行: node index.js
后,控制台输入
➜ server git:(master) ✗ node index.js mysql connncted success!
表示node服务链接mysql服务成功;
浏览器能够访问下localhost:3000/getList
{"code":0,"data":[{"id":1,"text":"haha","checked":0}],"message":"success"}
页面将会出现刚才咱们sql插入到数据库的数据
既然代码没有问题,那么咱们接下来就把他构建成镜像。
构建以前须要把代码中opt的host localhost改成本身主机的ip。由于容器启动的话,链接mysql须要经过主机的3308端口访问。
在当前文件夹新建名为Dockerfile的文件
# 基于最新的 node 镜像 FROM node:8 # 复制当前目录下全部文件到目标镜像 /app/ 目录下 COPY . /todolist/server # 修改工做目录 WORKDIR /todolist/server # 安装依赖 RUN ["npm", "install"] # 启动 node server ENTRYPOINT ["node", "index.js"]
执行:docker build -t mynode .
,生成node镜像
可经过docker images
查看本地的镜像。
➜ server git:(master) ✗ docker images REPOSITORY TAG IMAGE ID CREATED SIZE mynode latest 3e8de2825063 4 seconds ago 898MB
能够看到第一个镜像就是咱们刚刚构建的镜像
➜ server git:(master) ✗ docker images REPOSITORY TAG IMAGE ID CREATED SIZE mynode latest 3e8de2825063 4 seconds ago 898MB
接下来运行基于这个镜像的容器
执行:docker run --name mynode -d -p 4000:3000 mynode
启动成功后,访问下localhost:4000/getList
{"code":0,"data":[{"id":1,"text":"haha","checked":0}],"message":"success"}
能够看到页面输出咱们上面执行sql语句插入的数据
上面贴的代码只是基础的查看列表与插入数据两个方法,其余的请参考server
todolist的静态页面,我是经过vue-cli3搭建的。
执行vue create app
建立项目。
进入项目根目录执行npm run serve
页面是否正常执行。
而后编写简易的具备增删改查的todolist应用。具体代码见todolist。
注意vue.config.js中的devServer配置的target: 'http://127.0.0.1:4000'代理到咱们刚启动的node容器
页面启动成功后,访问localhost:8080
能够看到页面加载成功,列表也成功渲染出上面构建mysql时,sql插入的数据。
本地启动静态并请求服务端成功后,接下来也将静态页面打包成镜像,而后启动静态页面容器
在打包镜像容器以前,记得先将vue.config.js中的devServer配置的target: 'http://<主机ip地址>:4000'代理到咱们刚启动的node容器
编写Dockerfile
# 基于最新的 node 镜像 FROM node:8 # 复制当前目录下全部文件到目标镜像 /app/ 目录下 COPY . /todolist/app # 修改工做目录 WORKDIR /todolist/app RUN npm config set registry https://registry.npm.taobao.org && npm install # RUN ["npm", "install"] # 启动 node server ENTRYPOINT ["npm", "run", "serve"]
cd到静态页面的根目录执行: docker build -t static .
执行:docker run --name static -d -p 9000:8080 static
启动静态容器
打开浏览器访问localhost:9000
,能够看到页面成功渲染出列表页。
至此,mysql、node、vue容器均已互通。代码须要完善的地方详见todolist
咱们不可能每次部署一个应用,须要手动启动好几个服务。这个时候就须要使用docker-compose
关于命令就不介绍了,这里贴下连接
docker-compose命令
在根目录下新建docker-compose.yml
配置文件
version: '2' services: static: build: ./app/ container_name: static ports: - 7001:8080 depends_on: - nodejs - db nodejs: build: context: ./server/ dockerfile: sleep-dockerfile container_name: nodejs ports: - 4000:3000 environment: - IS_START_BY_COMPOSE=1 command: sh ./sleep.sh depends_on: - db db: image: mysql:5.6 container_name: db environment: MYSQL_ROOT_PASSWORD: "123456" command: --default-authentication-plugin=mysql_native_password --character-set-server=utf8mb4
具体配置,详见上面贴的连接。下面我介绍下我所写的配置
接下来解释下上面用compose启动的服务
值得一提的是,mysql的Dockerfile中作了建立数据库与表的操做。会涉及到关闭数据库密码登陆功能。由于关闭以后,操做数据库就不须要输入密码了。等表建完以后在恢复密码。
nodejs中的sleep.sh脚本是由于depends_on这个依赖只是单纯的等待其余服务开始启动,并非等待依赖的服务启动完成以后才开始构建自身的服务。这个时候node初始化会在mysql启动完成以前启动。这样的话,node启动的时候链接mysql就会报错,致使node服务挂掉。因此引用了sleep.sh,让node延迟一段时间启动。
最后在docker-compose
文件所在的目录下执行docker-compose build
再执行:docker-compose up
就能够启动todolist这个应用的全部服务了。