DockerFile基础指令
#利用FROM命令设置基准镜像,也就是我们要使用的镜像
FROM tomcat:latest
#将目录跳转,类似cd /usr/local/tomcat/webapps
WORKDIR /usr/local/tomcat/webapps
#会将本地docker-web下所有文件复制到容器中/usr/local/tomcat/webapps下的docker-web
ADD docker-web ./docker-web
构建docker镜像:
docker build -t feng/mydocker-web:1.0 /home/feng/docker-learn
#feng/mydocker-web 为镜像名字,1.0为版本号。/home/feng/docker-learn是Dockerfile文件的目录
FROM - 基于基准镜像
FROM centos #制作基准镜像(基于centos:lastest)
FROM scratch #不依赖任何基准镜像base image
FROM tomcat:9.0.22-jdk8-openjdk #拉取9.0.22-jdk8-openjdk版本的tomcat
LABEL - 说明信息(注释)
LABEL maintainer = "镜像作者"
LABEL version = "1.0"
LABEL description = "镜像描述"
WORKDIR- 设置工作目录
WORKDIR /usr/local
WORKDIR /usr/local/feng #如果不存在feng目录,则会自动创建
尽量使用绝对路径
ADD - 复制文件
ADD hello / #复制到根路径
ADD test.tar.gz / #添加根目录并解压3. ADD 除了复制,还具备添加远程文件功能
ADD 除了复制,还具备添加远程文件功能
ENV - 设置环境常量
ENV JAVA_HOME /usr/local/openjdk8
RUN ${JAVA_HOME}/bin/java -jar test.jar
尽量使用环境常量,可提高程序维护性
EXPOSE - 暴露容器端口
EXPOSE 8080
docker run -p 8000:8080 tomcat
DockerFile 执行命令
RUN &CMD&ENTRYPOINT
RUN : 在Build构建时执行命令
RUN yum install -y vim #Shell命令格式,安装vim
ENTRYPOINT : 容器启动时执行的命令,DockerFile中只有最后一个ENTRYPOINT会被执行
ENTRYPOINT ["ps"]
CMD : 容器启动后执行默认的命令或参数,DockerFile中也只有最后一个CMD会被执行,并且如果容器启动时有附加指令,则CMD会被忽略。
CMD ["java","-jar","text.jar"] #Exec格式,表示容器启动后查看当前运行状态
RUN和CMD、ENTRYPOINT的执行时间点不同
通过DockerFile构建镜像
构建mysql5.7镜像
创建Dockerfile文件
#拉取mysql镜像
FROM mysql:5.7
#设置工作目录
WORKDIR /docker-entrypoint-initdb.d
#将init.sql放入工作目录
ADD init.sql ./
通过dockerfile构建mysql镜像,并且初始化数据
root@DESKTOP-0K57HD8:/home/feng/docker_sampleDB# pwd
/home/feng/docker_sampleDB
root@DESKTOP-0K57HD8:/home/feng/docker_sampleDB# ls
Dockerfile init.sql
root@DESKTOP-0K57HD8:/home/feng/docker_sampleDB# docker build -t sample-db:1.0 /home/feng/docker_sampleDB
运行容器
root@DESKTOP-0K57HD8:~# docker run -t -p 3310:3306 --name=mysql -d sample-db:1.0
634a7914f75bfcfaf6790d57e0074de195592f19aa0b000157c89263e4c99840
root@DESKTOP-0K57HD8:~#
构建redis 6.2.10镜像
创建Dockerfile文件
# 拉取centos7镜像
FROM centos:centos7
# 安装redis需要的环境
RUN yum install -y gcc gcc-c++ net-tools make
# cd /usr/local
WORKDIR /usr/local
# 将redis安装包解压到/usr/local目录下
ADD redis-6.2.10.tar.gz .
# cd /usr/local/redis-6.2.10/src
WORKDIR /usr/local/redis-6.2.10/src
# 编译安装redis
RUN make && make install
# cd /usr/local/redis-6.2.10/
WORKDIR /usr/local/redis-6.2.10/
# 将redis.conf文件放入/usr/local/redis-6.2.10/文件夹下
ADD redis.conf ./
# 暴露 6379端口
EXPOSE 6379
# 运行reids
CMD ["redis-server","redis.conf"]
构建redis镜像
root@DESKTOP-0K57HD8:/home/feng/docker_redis# ls
Dockerfile redis-6.2.10.tar.gz redis.conf
root@DESKTOP-0K57HD8:/home/feng/docker_redis# docker build -t fneg/myredis:6.2.10 /home/feng/docker_redis/
运行redis容器
root@DESKTOP-0K57HD8:/home/feng/docker_redis# ls
Dockerfile redis-6.2.10.tar.gz redis.conf
root@DESKTOP-0K57HD8:/home/feng/docker_redis# docker run -t -p 3310:3306 -d feng/mydocker-web:1.0
容器间基于Link单向通信
容器间的通信可以通过ip进行通信,但是随着容器的增加,ip也不断增多,不利于后续管理
所以这里就可以使用单项连接来进行,此时,就可以通过容器名称ping
root@DESKTOP-0K57HD8:/home/feng/docker-learn# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
link-test latest 4c9e63d03518 6 minutes ago 699MB
fneg/myredis 6.2.10 02b0d15a460a 18 hours ago 652MB
sample-db 1.0 5a173d9308cb 36 hours ago 448MB
feng/mydocker-web 1.0 3aa2392dbc61 38 hours ago 680MB
root@DESKTOP-0K57HD8:/home/feng/docker-learn# docker run -t -d --name=link1 link-test
6ea7387bcd53611769d6937aeecb1d7919c2bb4203469ae7006a6eef52911e1e
root@DESKTOP-0K57HD8:/home/feng/docker-learn# docker run -t -d --name=link2 --link link1 link-test
7aadb7a7758f6c1b47498d422630bbb8fb54ef4db112c7afd6d79b3c89d745f2
root@DESKTOP-0K57HD8:/home/feng/docker-learn# docker exec -it link2 /bin/bash
root@7aadb7a7758f:/usr/local/tomcat/webapps# ping link1
PING link1 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: icmp_seq=0 ttl=64 time=0.096 ms
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.046 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.119 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.079 ms
但是Link单项通信的缺点也很明显,必须双方都简历对方的Link单项通信,才可以互相访问,否则只能单项访问。
Bridge网桥双向通信
网桥就类似于虚拟网卡,是docker环境中与外界环境通信必不可少的组件,网桥可以实现容器与容器之间的通信,也可以实现容器与外部环境的通信
创建好一个新的网桥以后,在网桥上添加容器,该网桥上的所有容器就可以相互通讯了
查看网桥:
root@DESKTOP-0K57HD8:~# docker network ls
NETWORK ID NAME DRIVER SCOPE
f6badd8665cc bridge bridge local
08518dd80233 host host local
e9dd6a187c45 none null local
root@DESKTOP-0K57HD8:~#
新建网桥:创建一个名字为my-bridge的网桥
root@DESKTOP-0K57HD8:~# docker network create -d bridge my-bridge
559c0bc3128a7814b0823cd5dbcfd29c6422beb07c42815d96ae6f680a6c9421
root@DESKTOP-0K57HD8:~#
将容器加入网桥,进入容器,测试容器之间网络是否可以连通
root@DESKTOP-0K57HD8:~# docker run -t -d --name=b1 bridge-test
633f205851c28b91877974aad7c4bc5b0b19853f9760988715811698cfa0413c
root@DESKTOP-0K57HD8:~# docker run -t -d --name=b2 bridge-test
924b8a3ad2521f9fdbdddb1bf502e9be90d787d9f0d8ccfb22cb9dbe818abce6
root@DESKTOP-0K57HD8:~# docker network connect my-bridge b1
root@DESKTOP-0K57HD8:~# docker network connect my-bridge b2
root@DESKTOP-0K57HD8:~#
root@DESKTOP-0K57HD8:~# docker exec -it b1 /bin/bash
root@633f205851c2:~# ping b2
PING b2 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: icmp_seq=0 ttl=64 time=0.079 ms
64 bytes from 172.18.0.3: icmp_seq=1 ttl=64 time=0.123 ms
volume数据卷
为什么使用数据卷?
1.由于容器中的数据在容器销毁过后就会被清除,如果使用docker搭建redis或者mysql之类的有持久化的应用,那么在容器被销毁后数据也可能被销毁,而docker容器销毁是经常会出现的场景,所以需要使用volume数据卷将容器的数据挂载到宿主机目录中。
2.volume可以实现容器与容器之间的数据共享
使用名称为volume-test的镜像构建容器
#将宿主机上的/home/feng/docker-learn/docker-web目录挂载到容器中的/usr/local/tomcat/webapps目录下
root@DESKTOP-0K57HD8:/home/feng/docker-learn/docker-web# ls
web
root@DESKTOP-0K57HD8:/home/feng/docker-learn/docker-web# docker run --name=v1 -t -d -p 8100:8080 -v /home/feng/docker-learn/docker-web:/usr/local/tomcat/webapps volume-test
root@DESKTOP-0K57HD8:/home/feng/docker-learn/docker-web# curl http://localhost:8100/web/index.html
<h1>hello docker</h1>
root@DESKTOP-0K57HD8:/home/feng/docker-learn/docker-web#
Docker Compose单机多容器部署工具
为什么需要Docker Compose?
在实际的生产环境中,往往需要多个容器配合工作,才能称的上一个完整的应用服务。
举个栗子,你想搭建一个 Web 服务,除了 Web 服务容器本身,若涉及数据存储,就需要依赖数据库容器(Mysql、Mongdb 等);若想实现分词搜索,就需要依赖搜索引擎容器(Elasticsearch、Solor 等);其他诸如缓存容器、负载均衡容器等。
同时,部署和管理繁多的容器服务是非常困难的。有了
Docker Compose
,就能很好的解决这个问题!Docker Compose
通过一个声明式的配置文件docker-compose.yml
来描述整个应用,使用一条命令即可完成部署。应用部署成功后,还可以通过一系列简单的命令实现对应用生命周期的管理。甚至,配置文件还可以置于版本控制系统中进行存储和管理。
使用一个java项目和mysql做一个示例:
首先创建jar和mysql文件夹,并且创建一个docker-compose.yml文件
root@DESKTOP-0K57HD8:/home/feng# ls
docker-compose.yml jar mysql
然后将jar包放入jar文件夹,并创建Dockerfile文件
FROM openjdk:8u222-jre
WORKDIR /usr/local/jre
ADD imgCdn.jar .
EXPOSE 8080
CMD ["nohup","java","-jar","imgCdn.jar"]
加将初始化语句放入mysql,并创建Dockerfile文件
FROM mysql:5.7
WORKDIR /docker-entrypoint-initdb.d
EXPOSE 3306
ADD init-db.sql .
编辑docker-compose.yml文件
version: '3.3'
services:
db:
build: ./mysql/ #根据mysql目录下的Dockerfile构建镜像
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
app:
build: ./jar/ #根据jar目录下的Dockerfile构建镜像
depends_on:
- db #可以使用db代替ip,同时Springboot中yml数据库ip地址也要改为db
ports:
- "8100:8080"
restart: always
进入docker-compose.yml目录执行docker-compose build构建镜像和docker-compose up -d运行容器
root@DESKTOP-0K57HD8:/home/feng# ls
docker-compose.yml jar mysql
root@DESKTOP-0K57HD8:/home/feng# docker-compose up -d