⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 bugpool.blog.csdn.net/article/details/105467335 「bugpool」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

前言

Docker是当下使用最多的一种容器技术,想精通Docker并不容易,在公司生产中会有专门的运维人员负责。但是身为开发人员,适当的学习Docker是必要的。Docker的好处这里就不介绍了,网上一搜一大堆。

本篇将用最简短的篇幅介绍开发人员需要学习的Docker干货,你将学习到

  • Docker的安装
  • 第一个HelloWorld镜像
  • 运行nginx并访问静态页面
  • 运行mysql数据库
  • 制作自己的镜像

概念

Docker最重要的3个概念:仓库、镜像、容器,以springboot项目为例:

  • **镜像(Image): ** 将jdk + 项目jar包等文件以Docker的形式打包在一起就是镜像。这个概念跟重装系统时用的镜像是很相似的
  • 容器(Container): 将镜像实例化启动起来就是容器。容器是一个轻量级的linux系统,root用户权限、进程空间、用户空间和网络空间容器都有。假设现在想要部署一个redis,你得解压、安装、配置环境变量吧,但是docker不一样,只要有人把redis的镜像做好,运行起来成为一个小linux(也就是容器),这些环境跟做镜像的人的环境就会是一毛一样的,用户只需要run就行了
  • 仓库(Repository): 这里的仓库用于存放镜像,github就是代码的仓库,而这里的docker hub也就是存放镜像的仓库,供用户pull

docker跟git是十分相识的,通常我们会进行一下操作

  • 通过pull命令到docker hub上拉取需要的镜像,比如mysql、redis等等
  • 镜像已经拉取到本地了,通过run命令将镜像运行起来成为容器
  • 以上两步是使用他人的镜像,而当自己要构建一个例如springboot的镜像时,使用build命令构建镜像

一、连接linux

本篇使用的服务器是ubuntu,没有服务器的同学也可以使用虚拟机,效果是一样的

# ssh 用户名@ip地址
chaitous-Mac-mini:~ chaitou$ ssh ubuntu@148.70.139.121
ubuntu@148.70.139.121's password:
Welcome to Ubuntu 16.04.1 LTS (GNU/Linux 4.4.0-157-generic x86_64)

# 如果连接不上的,可能是你本机之前有其他服务的缓存和公钥信息
# 使用`ssh-keygen -R 148.70.139.121`清一下

如果是学生或者还没有接触过服务器的同学,笔者还是建议去买一个,现在面向新用户一年就几十块钱。能接触到公网,买个域名也能让项目真实的接触一下生产环境。

二、安装docker

# 先切换到root用户下
sudo su

# 更新apt-get,保证apt-get最新版本
apt-get update

# 安装docker
apt-get install -y docker.io

# 查看docker版本
docker version

# 启动docker服务(有可能不需要这一步,多执行一遍也不会有错)
service docker start

# 再执行一次version,看到Client、Service说明启动成功了
docker version
Client:
Version: 18.09.7
API version: 1.39
Go version: go1.10.4
Git commit: 2d0083d
Built: Fri Aug 16 14:19:38 2019
OS/Arch: linux/amd64
Experimental: false

Server:
Engine:
Version: 18.09.7
API version: 1.39 (minimum version 1.12)
Go version: go1.10.4
Git commit: 2d0083d
Built: Thu Aug 15 15:12:41 2019
OS/Arch: linux/amd64
Experimental: false

三、第一个Docker镜像hello world

步骤:

  • 先用pull命令从远端拉镜像到本地
  • 用images命令查看所有镜像
  • run命令运行镜像

# pull: 从仓库拉取镜像
# docker pull [options] name[:tag]
# docker pull [可选参数] 镜像名[:版本号](如果不填默认为最新版本)
docker pull hello-world
# 默认从docker官方获取镜像,很可能因为网络原因需要多拉取几次

# 查看本机上的所有镜像
# docker images [可选参数]
docker images
# 看到hello-world说明拉取成功了
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest fce289e99eb9 15 months ago 1.84kB

# 运行镜像
# docker run [options] image[:tag] [command] [args]
# docker run [可选参数] 镜像名[:版本号] [镜像运行时要执行的命令] [命令参数]
docker run hello-world

Hello from Docker!
# 当你看到这条消息说明安装成功了
This message shows that your installation appears to be working correctly.
# 生成这条信息,docker做了以下几个步骤
To generate this message, Docker took the following steps:
# client端(也就是终端,命令行)连接到daemon端(指的是我们本地docker)
1. The Docker client contacted the Docker daemon.
# daemon端(本地docker)到Docker hub仓库中拉取了hello-world镜像
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
# daemon端(本地docker)从镜像中创建了一个容器,这个镜像运行了当前看到输出的代码
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
# daemon端(本地docker)将输出流给client端(命令行),显示到终端
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.

配置加速器

docker hub毕竟是境外网站,可能会网络超时,因此配置一下阿里镜像加速器

打开阿里云https://cr.console.aliyun.com/,登录一下aliyun,按着下面的提示配置一遍

四、运行nginx

# 拉取nginx镜像
docker pull nginx

# 查看镜像
docker images

# REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest ed21b7a8aee9 12 days ago 127MB
hello-world latest fce289e99eb9 15 months ago 1.84kB

运行方式

刚刚run命令运行了hello world,这里详细将一下,运行方式有2种,前台运行和后台运行,前台运行则会占用终端,一般都会选择让容器在后台运行

前台运行,这种方式终端将不能进行其他操作,使用Ctrl+C停止

docker run nginx

后台运行,更常用的方式应该是这种

# 可以用docker run --help查看一下帮助文档,其中有这么一条
docker run --help
...
-d, --detach Run container in background and print container ID
...

# 使用-d后台运行nginx
docker run -d nginx
# 返回的是容器Id
7f7468b0d50ddea5bd258e78339d8c8a3681a7d601c82000bde1c6653e273c13

# docker ps 查看当前运行的容器
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7f7468b0d50d nginx "nginx -g 'daemon of…" 46 seconds ago Up 45 seconds 80/tcp dazzli

# 终止容器运行
docker stop 7f
7f

网络

刚刚提到docker容器就是一个小linux,也就是一个虚拟机。而容器行跟外界交互,只能先通过ubuntu主机的网卡,才能跟外界交互。主机与docker容器网络通讯的方式有为3种:

  • 桥接(Bridge): 也是最常用的方式,该模式下会将ubuntu主机上的端口映射到docker容器的端口上,例如8080:8081则会- 将主机上的8080端口映射到docker容器的8081端口
  • 共享(Host): ubuntu主机与docker共享同一端口
  • 无网络(None): docker没有网络,外界无法访问

我们重点讲解一下最常用的桥接模式

桥接 Bridge

桥接模式需要使用-p参数或者-P参数,-p 主机端口:容器端口,-P则使用随机的主机端口映射到docker容器

  1. -p 指定端口模式

# docker run -d -p 主机端口:容器端口 image[:tag]
docker run -d -p 8080:80 nginx
5e0cc45d89288faf9ba04b5e8b30548b8c14409a6d93e1abdd297676a7b7769a

docker stop 5e

此时我们就可以通过:8080访问nginx了

-P 随机端口

可以看到docker自动将0.0.0.0:32768->80/tcp随机端口32768映射到80上

# 随机开启一个端口映射到容器
# docker run -d -P image[:tag]
docker run -d -P nginx

docker ps
# 可以看到是32768端口映射到80端口
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
be30acaeb546 nginx "nginx -g 'daemon of…" 10 seconds ago Up 9 seconds 0.0.0.0:32768->80/tcp trusting_keller

docker stop be

五、运行mysql

使用docker进行mysql的部署比起在ubuntu上部署简直不要太方便!打开阿里云https://cr.console.aliyun.com/

跳转到mysql的镜像地址查看mysql在docker下的使用。

链接地址:https://hub.docker.com/_/mysql

使用步骤:

  • 从远端仓库拉取mysql
  • 通过docker run运行
  • -d进行后台运行
  • -p指定端口映射
  • -e后面跟着的是mysql的参数,通过上方连接可以查询到通过MYSQL_ROOT_PASSWORD设置数据库密码、MYSQL_DATABASE设置数据库名

docker pull mysql

docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=leilema -e MYSQL_DATABASE=leilema mysql:latest

通过数据库连接工具,例如Navicat等等进行数据连接,验证

是不是很简单,傻瓜式部署啊。特别是停止mysql容器跟删除mysql镜像,以前都是执行一大堆脚本还删不干净,现在就暴力多了,直接容器一停,镜像已删除,相当于整个虚拟linux全部删掉,要多干净有多干净,关键还快!

# 停止容器
docker stop 容器ID

# 删除镜像
docker rmi image[:tag]

错误(*进入容器内部)

2059错误: Authentication plugin 'caching_sha2_password' cannot be loaded

这个错误不难,装mysql时也遇到过,通过google 2059错误,知道解决方案是要给进入到mysql,设置一下ALTER USER 'root' IDENTIFIED WITH mysql_native_password BY 'leilema';才能连接。

难面也是会有错误的发生,既然docker容器就是一个虚拟linux,我们偶尔也是要进入到docker容器中查查日志啊,改改配置文件什么的。真好顺着这个错误,学习一下如何进入容器内部,也顺便看看容器内部是什么样子的:

  • 通过docker ps查询容器id
  • 通过docker exec -it 容器ID(可以只输入前缀) bash进入容器,此时你会发现终端前方的用户从root@VM-0-12-ubuntu改变成了root@9d71ee58f07c,@后方跟着的正式我们的容器id
  • 进入容器后的操作就跟linux的操作是一样的,最后通过exit退出mysql和容器

root@VM-0-12-ubuntu:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9d71ee58f07c mysql:latest "docker-entrypoint.s…" 8 minutes ago Up 8 minutes 0.0.0.0:3306->3306/tcp, 33060/tcp hardcore_nash
root@VM-0-12-ubuntu:~# docker exec -it 9d bash

# 进入容器内部,ls可以看到这货就是一个linux
root@9d71ee58f07c:/# ls
bin docker-entrypoint-initdb.d home media proc sbin tmp
boot entrypoint.sh lib mnt root srv usr
dev etc lib64 opt run sys var

# 进入mysql
root@9d71ee58f07c:/# mysql --user=root --password
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
...
# 执行一下命令,修改下mysql密码
mysql> ALTER USER 'root' IDENTIFIED WITH mysql_native_password BY 'leilema';
Query OK, 0 rows affected (0.01 sec)

mysql> exit
Bye
root@9d71ee58f07c:/# exit
exit

六、制作自己的镜像

想要制作自己的镜像需要有2步操作:

  • 编写Dockerfile,说明镜像要如何进行创建,跟makefile有点像
  • 通过docker build命令构建镜像

编写Dockerfile

这里以springboot项目为例,手头有springboot项目的同学可以直接使用手头的。我这里提供一个sringboot构建helloworld的jar包,已经传到git上,因此

  • 使用git拉取项目(或者自己通过rz命令将jar包传到服务器上)
  • cd到jar包目录下,在同级目录开始编写Dockerfile文件

get clone https://gitee.com/chaitou/hello-springboot

cd hello-springboot
vim Dockerfile

dockerfile文件如下:

# 依赖的基础镜像
from java:8
# 创建者
MAINTAINER bugpool xxx@163.com
# 将当前目录下的jar复制到容器/目录下
COPY hello-springboot.jar /hello-springboot.jar
# 指定启动时运行java -jar 命令
ENTRYPOINT ["java", "-jar","/hello-springboot.jar"]

构建镜像

springboot项目肯定是需要需要jdk才能运行,dockerfile上也写了from java:8,因此

  • 需要从仓库先pull一下java镜像
  • 使用docker build构建镜像,-t指定镜像名:版本号,最后一个.表示当前目录
  • 启动镜像,如果使用的是上面我提供的jar包,我特意将其运行端口改为8081来练习一下-p桥接网络的使用。

# 拉取java8
docker pull java:8
# 构建镜像
docker build -t hello-springboot:1.0 .
# 启动镜像
docker run -p 80:8081 hello-springboot:1.0

我们将主机80端口映射成为了docker容器的8081端口,因此我们需要访问ip:80/hello,80端口可以省略,因此就是ip/hello,如果看到一下界面,说明已经build成功,并且成功部署了

文章目录
  1. 1. 前言
  2. 2. 概念
  3. 3. 一、连接linux
  4. 4. 二、安装docker
  5. 5. 三、第一个Docker镜像hello world
    1. 5.0.1. 配置加速器
  • 6. 四、运行nginx
    1. 6.0.1. 运行方式
    2. 6.0.2. 网络
    3. 6.0.3. 桥接 Bridge
    4. 6.0.4. -P 随机端口
  • 7. 五、运行mysql
    1. 7.0.1. 错误(*进入容器内部)
  • 8. 六、制作自己的镜像
    1. 8.0.1. 编写Dockerfile
    2. 8.0.2. 构建镜像