CONTENTS
一、docker简介
1.1 docker相关概念
1.2 docker应用场景
1.3 docker和虚拟机比较
二、初识docker
2.1 安装docker
2.2 初识docker-docker架构
2.3 配置镜像加速器
三、docker命令详解
四、docker容器数据卷
五、docker应用部署
5.1 部署mysql
5.2 部署Tomcat
5.3 部署nginx
5.4 部署redis
六、docker compose批量管理容器
七、容器的迁移与备份
八、Docker-file开发自己的镜像
九、私有仓库的搭建与使用
- Docker 是一个开源的应用容器引擎,诞生于 2013 年初,基于 Go 语言实现, dotCloud 公司出品(后改名为Docker Inc)
- Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上。
- 容器是完全使用沙箱机制,相互隔离,容器性能开销极低。
- Docker 从 17.03 版本之后分为 CE(Community Edition: 社区版) 和 EE(Enterprise Edition: 企业版)(后面我会装CE版)
简化配置、代码流水线管理、提高开发效率、隔离应用、整合服务器、调试能力、多租户环境、快速部署(具体可参考下面的博客)
docker八大应用场景
而对于写代码的程序员来说,代码接触到好几个环境:开发环境、测试环境以及生产环境:
当代码从其中一个环境转移到另一个环境时,常常会遇见问题(明明在自己的机器上可以运行,转移到其他机器上时就出现问题了?)。这一般都是由于java环境配置不同而导致的。如果有了容器后,可以将自己的jdk环境和项目封装在一个容器中进行交付,就可以解决这个问题。通俗讲是容器可以解决代码之间水土不服的问题哦!
docker和虚拟机比
对于之前玩过虚拟机的小伙伴似乎也想知道虚拟机和docker之间的区别有哪些。先看看下面的图对比下:
再来了解下容器:容器就是将软件打包成标准化单元,以用于开发、交付和部署。
相同:
- 容器和虚拟机具有相似的资源隔离和分配优势
不同:
- 容器虚拟化的是操作系统,虚拟机虚拟化的是硬件。
- 传统虚拟机可以运行不同的操作系统,容器只能运行同一类型操作系统
Docker可以运行在MAC、Windows、CentOS、UBUNTU等操作系统上,本课程基于CentOS 7 安装Docker。官网:https://www.docker.com(本博客是在腾讯云购买云服务器进行操作的。操作系统的版本为centos7,建议用虚拟机,或者在腾讯云上购买服务器,按量收费,适合做实验)
还有一个安装docker的链接可供参考:https://www.jianshu.com/p/1e5c86accacb
- 镜像(Image):Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。
- 容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和对象一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
- 仓库(Repository):仓库可看成一个代码控制中心,用来保存镜像。
默认情况下,将来从docker hub(https://hub.docker.com/)上下载docker镜像,太慢。一般都会配置镜像加速器:
- USTC:中科大镜像加速器(https://docker.mirrors.ustc.edu.cn)
- 阿里云
- 网易云
- 腾讯云
下面我们来配置阿里云镜像加速器(推荐安装1.10.0以上版本的docker客户端):
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://c63ol3wn.mirror.aliyuncs.com"]
}
EOF
cat /etc/docker/daemon.json
systemctl daemon-reload
systemctl restart docker
- 启动docker服务器:systemctl start docker
- 停止docker服务:systemctl stop docker
- 重启docker服务:systemctl restart docker
- 查看docker服务状态:systemctl status docker
- 设置开机启动docker服务:systemctl enable docker
查看镜像: 查看本地所有的镜像
docker images
docker images –q # 查看所用镜像的id
搜索镜像:从网络中查找需要的镜像
docker search 镜像名称
拉取镜像:从Docker仓库下载镜像到本地,镜像名称格式为 名称:版本号,如果版本号不指定则是最新的版本。如果不知道镜像版本,可以去docker hub 搜索对应镜像查看。
docker pull 镜像名称
删除镜像: 删除本地镜像
docker rmi 镜像id # 删除指定本地镜像
docker rmi `docker images -q` # 删除所有本地镜像
查看容器:
docker ps # 查看正在运行的容器
docker ps –a # 查看所有容器
创建并启动容器:
docker run 参数
参数说明:
- -i:保持容器运行。通常与 -t 同时使用。加入it这两个参数后,容器创建后自动进入容器中,退出容器后,容器自动关闭。
- -t:为容器重新分配一个伪输入终端,通常与 -i 同时使用。
- -d:以守护(后台)模式运行容器。创建一个容器在后台运行,需要使用docker exec 进入容器。退出后,容器不会关闭。
- -it 创建的容器一般称为交互式容器,-id 创建的容器一般称为守护式容器
- --name:为创建的容器命名。
进入容器:
docker exec 参数 # 退出容器,容器不会关闭
停止容器:
docker stop 容器名称
启动容器:
docker start 容器名称
删除容器:如果容器是运行状态则删除失败,需要停止容器才能删除
docker rm 容器名称
查看容器信息
docker inspect 容器名称
这个章节可以参考这篇博客,写的很详细哦(偷个懒):
https://www.cnblogs.com/kevingrace/p/6238195.html
在Docker容器中部署MySQL,并通过外部mysql客户端操作MySQL Server。
实现步骤:
(1)搜索mysql镜像
(2)拉取mysql镜像,一般我们会选择stars越多的镜像,毕竟受欢迎嘛,也可以加上指定的版本号。
docker pull mysql:5.6
(3)创建容器,设置端口映射、目录映射
# 在/root目录下创建mysql目录用于存储mysql数据信息
mkdir ~/mysql
cd ~/mysql
docker run -id \-p 3307:3306 \--name=a_mysql \-v $PWD/conf:/etc/mysql/conf.d \-v $PWD/logs:/logs \-v $PWD/data:/var/lib/mysql \-e MYSQL_ROOT_PASSWORD=123456 \mysql:5.6
#参数说明:
-p 3307:3306:将容器的 3306 端口映射到宿主机的 3307 端口。
-v $PWD/conf:/etc/mysql/conf.d:将主机当前目录下的 conf/my.cnf 挂载到容器的 /etc/mysql/my.cnf。配置目录
-v $PWD/logs:/logs:将主机当前目录下的 logs 目录挂载到容器的 /logs。日志目录
-v $PWD/data:/var/lib/mysql :将主机当前目录下的data目录挂载到容器的 /var/lib/mysql 。数据目录
-e MYSQL_ROOT_PASSWORD=123456:初始化 root 用户的密码。
了解下端口映射的概念:
(4)如果你是虚拟机的可以直接关掉防火墙,我是云主机,所以也要去编辑下出站规则(实验嘛,全放通好勒)。
(5)进入容器并操作mysql
#进入a_mysql容器中
docker exec -it a_mysql bash
#登录mysql
mysql -uroot -p123456
#创建test数据库做测试用
mysql> create database test;
mysql> use mysql;
mysql> select host,user from user;
+-----------+------+
| host | user |
+-----------+------+
| % | root |
| localhost | root |
+-----------+------+
#开始给root授权可以远程访问,这边注意了,因为这边只是测试用的,实际生产环境下权限不能这么给的哦
mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '123456' WITH GRANT OPTION;
mysql> FLUSH PRIVILEGES;
(6)客户端连接mysql
我利用workbench连接mysql的:
在这可以看到我刚才创建的数据库test
在Docker容器中部署Tomcat,并通过外部机器访问Tomcat部署的项目。
#1 搜索tomcat镜像
docker search tomcat
#2 拉取tomcat镜像
docker pull tomcat
#3 创建容器,设置端口映射、目录映射
docker run -di --name=mytomcat -p 9000:8080 -v /usr/local/tomcat/webapps:/usr/local/tomcat/webapps tomcat
注意:宿主机的/usr/local/tomcat/webapps这个目录是用来放置网页相关的东西的,默认访问ip:9000是没法访问的,找不到网页,因为还没在webapps目录中放东西,但如果我在创建docker容器的时候不进行目录的挂载的话,浏览器访问就应该是Tomcat的默认访问页面,在后面的docker compose中会说到这个。
直接拉取镜像,启动镜像,然后通过浏览器访问:
需要注意的是:nginx默认访问端口就是80,如果被占用了80端口,那么在指定映射的时候可以改变宿主机的端口映射,在访问时也需要带上端口号。
docker pull nginx #拉取镜像
docker images #查看镜像
docker run -id --name=mynginx -p 80:80 nginx #运行容器
浏览器中访问自己的IP,默认80:
(1)搜索redis镜像
docker search redis
(2)拉取redis镜像
docker pull redis:5.0
(3)创建容器,设置端口映射
docker run -id --name=myredis -p 6379:6379 redis:5.0
(4)可以进入容器中看看
docker exec -it myredis /bin/bash
(5)登入本机测试看看
root@fb367ad13134:/data# cd /usr/local/bin/
root@fb367ad13134:/usr/local/bin# ls
docker-entrypoint.sh redis-benchmark redis-check-rdb redis-sentinel
gosu redis-check-aof redis-cli redis-server
root@fb367ad13134:/usr/local/bin# ./redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> set str test
OK
127.0.0.1:6379> get str
"test"
(6)使用外部机器连接redis,先下载个客户端Redis
yum install redis.x86_64 -y
redis-cli -h 129.211.186.178 -p 6379
129.211.186.178:6379> set str test2
OK
129.211.186.178:6379> get str
"test2"
129.211.186.178:6379>
Compose项目是Docker官方的开源项目,负责实现对Docker容器集群的快速编排。它是一个定义和运行多容器的docker应用工具。使用compose,你能通过YMAL文件配置你自己的服务,然后通过一个命令, 你能使用配置文件创建和运行所有的服务。所以我们就用docker compose来实现容器的快速编排(按照一定的业务规则批量管理容器)。
使用步骤:
1.利用 Dockerfile 定义运行环境镜像2.使用 docker-compose.yml 定义组成应用的各服务3.运行 docker-compose up 启动应用
下面我们开始利用docker compose批量部署mysql,Tomcat,nginx和Redis
(1)安装Docker Compose
# Compose目前已经完全支持Linux、Mac OS和Windows,在我们安装Compose之前,需要先安装Docker。下面我们以编译好的二进制包方式安装在Linux系统中。
curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
# 设置文件可执行权限
chmod +x /usr/local/bin/docker-compose
# 查看版本信息
docker-compose -version
如果卸载Docker Compose执行下面的命令,我就不操作了。
# 二进制包方式安装的,删除二进制文件即可
rm /usr/local/bin/docker-compose
(2)创建目录
#创建docker-compose目录
mkdir ~/docker-compose
cd ~/docker-compose
(3)编辑docker-compose.yml 文件
先大概了解下配置的一个容器信息,注意它们各处的网络(比如下面dev和pro都是自定义的网络),属于同一网络的容器可以互相访问.
配置文件可参考下面:
version: '3'
services:
nginx1:
image: nginx
ports:
- 80:80
container_name: "nginx1"
networks:
- pro
redis1:
image: redis
ports:
- "6379:6379"
container_name: "redis1"
networks:
- dev
mysql1:
image: mysql
environment:
MYSQL_ROOT_PASSWORD: "root"
ports:
- "3306:3306"
container_name: "mysql1"
networks:
- dev
web1:
image: tomcat
ports:
- "9090:8080"
container_name: "web1"
networks:
- dev
- pro
networks:
dev:
driver: bridge
pro:
driver: bridge
(4)重启docker,并设置docker compose后台启动:
systemctl restart docker
#执行下面命令它会自动创建容器和网络,有出错信息注意yml文件的语法格式
docker-compose up -d
(5)运行检测
咱们访问Tomcat试试看,如果又出现404界面,不用担心:进入容器并把webapps.dists里的文件copy到webapps中。
docker exec -it web1 /bin/bash
cp webapps.dist/* webapps
然后我们打开浏览器访问试试,大功告成。
目标:能够将容器保存为镜像,备份,恢复镜像再启动以恢复的镜像作为基础的容器。
分析:在当前的容器中安装了各种组件;期望在其他服务器上也能快速拥有该容器的一切环境;可以将当前的容器制作为一个镜像,再将该奖项复制到其他服务器,其他服务器再基于镜像运行容器。
- 1.将容器保存为一个镜像;
- 2.备份镜像;
- 3.恢复镜像;
- 4.基于镜像运行容器
看看下面的图片有助于了解迁移备份的流程:
其中涉及到的命令有:
- docker commit 将容器保存为镜像
- docker save 将镜像备份为tar文件
- docker load 根据tar文件恢复为镜像
下面直接实战把(下面都是本地恢复,不同服务器之间也是可以的,只要把tar包copy到其他服务器就好了):
我们来运行mynginx容器并检测一下能否正常使用:
#因为前面我用docker compose运行了nginx1,所以先把它停掉
docker stop nginx1
#运行mynginx
docker run -id --name=mynginx -p 80:80 nginx
访问正常:
通过前面的学习我们知道要获得镜像,可以从Docker仓库中进行下载。那如果我们想自己开发镜像,就可以利用Dockerfile。
Dockerfile其实就是一个文本文件, 由一系列命令和参数构成,Docker可以读取Dockerfile文件并根据Dockerfile文件的描述来构建镜像。
Dockerfile文件内容一般分为4部分:
- 基础镜像信息
- 维护者信息
- 镜像操作指令
- 容器启动时执行的指令
关键字 | 作用 | 备注 |
---|---|---|
FROM | 指定父镜像 | 指定dockerfile基于那个image构建 |
MAINTAINER | 作者信息 | 用来标明这个dockerfile谁写的 |
LABEL | 标签 | 用来标明dockerfile的标签 可以使用Label代替Maintainer 最终都是在docker image基本信息中可以查看 |
RUN | 执行命令 | 执行一段命令 默认是/bin/sh 格式: RUN command 或者 RUN ["command" , "param1","param2"] |
CMD | 容器启动命令 | 提供启动容器时候的默认命令 和ENTRYPOINT配合使用.格式 CMD command param1 param2 或者 CMD ["command" , "param1","param2"] |
ENTRYPOINT | 入口 | 一般在制作一些执行就关闭的容器中会使用 |
COPY | 复制文件 | build的时候复制文件到image中 |
ADD | 添加文件 | build的时候添加文件到image中 不仅仅局限于当前build上下文 可以来源于远程服务 |
ENV | 环境变量 | 指定build时候的环境变量 可以在启动的容器的时候 通过-e覆盖 格式ENV name=value |
ARG | 构建参数 | 构建参数 只在构建的时候使用的参数 如果有ENV 那么ENV的相同名字的值始终覆盖arg的参数 |
VOLUME | 定义外部可以挂载的数据卷 | 指定build的image那些目录可以启动的时候挂载到文件系统中 启动容器的时候使用 -v 绑定 格式 VOLUME ["目录"] |
EXPOSE | 暴露端口 | 定义容器运行的时候监听的端口 启动容器的使用-p来绑定暴露端口 格式: EXPOSE 8080 或者 EXPOSE 8080/udp |
WORKDIR | 工作目录 | 指定容器内部的工作目录 如果没有创建则自动创建 如果指定/ 使用的是绝对地址 如果不是/开头那么是在上一条workdir的路径的相对路径 |
USER | 指定执行用户 | 指定build或者启动的时候 用户 在RUN CMD ENTRYPONT执行的时候的用户 |
HEALTHCHECK | 健康检查 | 指定监测当前容器的健康监测的命令 基本上没用 因为很多时候 应用本身有健康监测机制 |
ONBUILD | 触发器 | 当存在ONBUILD关键字的镜像作为基础镜像的时候 当执行FROM完成之后 会执行 ONBUILD的命令 但是不影响当前镜像 用处也不怎么大 |
STOPSIGNAL | 发送信号量到宿主机 | 该STOPSIGNAL指令设置将发送到容器的系统调用信号以退出。 |
SHELL | 指定执行脚本的shell | 指定RUN CMD ENTRYPOINT 执行命令的时候 使用的shell |
目标:
使用Dockerfile创建一个自定义jdk1 .8的镜像
分析:
假设在centos7作为基础镜像上,添加jdk1.8并构建一个包含jdk1.8的centos7新镜像。
-Dockerfile可以实现; Dockerfile是由一系列命令和参数构成的文本文件,在文件中可以指定各个组件资源和运行命令等。
实现步骤:
1.拉取centos7镜像;
2.上传jdk1.8;
3.编写Dockerfile文件;
4.构建镜像;
5.测试(基于新镜像创建并运行容器,运行java -version )
(1)首先拉取centos7镜像,创建文件夹并进入该文件夹中。下载jdk8的Linux版本通过xftp上传到该目录:
官网下载很慢,可通过网盘下载:
链接:https://pan.baidu.com/s/1TAPxbGfDCZS945dT1ji9sw
提取码:y0j6
docker pull centos:7
mkdir -p /usr/local/dockerjdk
cd /usr/local/dockerjdk
mv /root/jdk-8u221-linux-x64.tar.gz .
(2)编辑Dockerfile文件
[root@docker dockerjdk]# vim Dockerfile
FROM centos:7
MAINTAINER Gawain
WORKDIR /usr
RUN mkdir /usr/local/java
ADD jdk-8u221-linux-x64.tar.gz /usr/1oca1/java/
ENV JAVA_HOME /usr/1oca1/java/jdk1.8.0_221
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/1ib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/1ib:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATH
(3)执行命令构建镜像,不要忘记后面.
docker build -t='jdk1.8' .
(4)查看镜像是否创建成功
(5)运行jdk容器,查看java版本:
Docker官方的Docker hub(https://hub.docker.com)是一个用于管理公共镜像的仓库,我们可以从上面拉取镜像 到本地,也可以把我们自己的镜像推送上去。但是,有时候我们的服务器无法访问互联网,或者你不希望将自己的镜像放到公网当中,那么我们就需要搭建自己的私有仓库来存储和管理自己的镜像。
(1)拉取registry并启动
# 拉取私有仓库镜像
docker pull registry
# 启动私有仓库容器
docker run -id --name=registry -p 5000:5000 registry
(2)打开浏览器 输入地址http://私有仓库服务器ip:5000/v2/_catalog,看到{"repositories":[]} 表示私有仓库 搭建成功
(3)修改daemon.json
# 在下面这个文件里添加一个key,保存退出。此步用于让 docker 信任私有仓库地址;注意将私有仓库服务器ip修改为自己私有仓库服务器真实ip
vim /etc/docker/daemon.json
{"insecure-registries":["129.211.186.178:5000"]}
(4)重启docker 服务 并启动registry
systemctl restart docker
docker start registry
# 标记镜像为私有仓库的镜像
docker tag jdk1.8 129.211.186.178:5000/jdk1.8
# 重启私有仓库容器
docker restart registry
# 上传标记的镜像
docker push 129.211.186.178:5000/jdk1.8
(1)从本地镜像私有仓库拉取镜像
#再从镜像仓库拉取之前先删除本地的jdk1.8容器和镜像,注意用docker images查看
docker rm testjdk
docker rmi 129.211.186.178:5000/jdk1.8
docker images
#拉取镜像
docker pull 129.211.186.178:5000/jdk1.8
docker images
(2)其他服务器拉取私有仓库镜像
大多数情况下,都是某台服务器部署了私有镜像仓库之后;到其它服务器上从私有仓库中拉取镜像,若要拉取私有仓库镜像需要去修改docker的配置文件,设置启动时候的仓库地址。
编辑下面这个配置文件,添加如下一行(注意是自己的IP)
vim /usr/lib/systemd/system/docker.service
--add-registry=129.211.186.178:5000 --insecure-registry=129.211.186.178:5000\
#重新加载docker配置文件
systemctl daemon-reload
#重启docker
systemctl restart docker
拉取镜像:
docker pull jdk1.8
终于总结完了,学习使我快乐!