Docker 部署项目
目录
- Docker 部署项目
- 一、安装docker(Ubuntu)
- 二、docker仓库配置
- 1、设置公有仓库
- 2、设置私有仓库
- 1)搭建私有仓库——私有服务器上
- 2)设置私有仓库
- 三、拉取镜像
- 1、登录仓库
- 2、拉取镜像
- 四、dockerfile编写
- 1、RUN
- 2、COPY
- 3、CMD
- 4、ENV
- 5、ARG
- 6、VOLUME
- 7、EXPOSE
- 8、WORKDIR
- 9、USER
- 10、ONBUILD
- 11、ENTRYPOINT
- 12、Dockerfile案例
- 五、docker安装MySQL
- 1、下载指定版本镜像
- 2、启动容器
- 3、进入容器
- 4、可设置远程访问
- 六、docker容器间通信
- 1、案例
- 2、实现同主机容器间通信
- 3、容器加入网桥的方式
- 七、docker化部署流程
一、安装docker(Ubuntu)
- 由于apt官方库里的docker版本可能比较旧,所以先卸载可能存在的旧版本:
$ sudo apt-get remove docker docker-engine docker-ce docker.io
- 更新apt包索引:
$ sudo apt-get update
- 安装以下包以使apt可以通过HTTPS使用存储库(repository):
$ sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common
- 添加Docker官方的GPG密钥:
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
- 使用下面的命令来设置stable存储库:
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
- 再更新一下apt包索引:
$ sudo apt-get update
- 安装最新版本的Docker CE:
$ sudo apt-get install -y docker-ce
- 验证docker
$ systemctl status docker
docker正常启动,状态如下图:
- 若未启动,则启动docker服务:
$ sudo systemctl start docker
- 查看docker版本号验证
$ sudo docker -v
二、docker仓库配置
1、设置公有仓库
- 修改仓库配置文件
$ vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://registry.docker-cn.com"]
}
- 重启docker
$ systemctl daemon-reload
$ systemctl restart docker
常用国内加速站点:
https://registry.docker-cn.com 国内
http://hub-mirror.c.163.com 网易
https://3laho3y3.mirror.aliyuncs.com 阿里
http://f1361db2.m.daocloud.io
https://mirror.ccs.tencentyun.com
2、设置私有仓库
1)搭建私有仓库——私有服务器上
- 搭建工具
docker 官方提供了 registry
的镜像,可以使用它来建私有仓库。
- 环境
系统 | IP | 角色 |
Ubuntu 18.04 | 10.0.0.0 | docker 客户端服务器 |
Ubuntu 18.04 | 10.0.0.1 | docker 仓库服务器(root用户) |
- 都安装docker,修改docker源,并重启(参考一)
- 在10.0.0.1上拉取
registry
docker pull registry
- 在10.0.0.1上启动仓库
docker run -d --name docker-registry --restart=always -p 5000:5000 registry
2)设置私有仓库
- 客户端10.0.0.0设置私有仓库地址,并重启
$ vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://registry.docker-cn.com"],
"insecure-registries": ["10.0.0.1:5000"] # 设置私有仓库地址
}
systemctl restart docker
- 测试私有仓库
在10.0.0.0下载一个镜像,如alpine
sudo docker pull alpine
打tag,镜像名称由registry和tag两部分组成,registry完整格式:[registry_ip]:[registry:port]/[user]/[image_name:version]
sudo docker tag alpine 10.0.0.1:5000/alpine
- 上传本地镜像
sudo docker push 10.0.0.1:5000/alpine
- 查看仓库镜像
curl 10.0.0.1:5000/v2/_catalog
三、拉取镜像
1、登录仓库
sudo docker login -u [user] -p [password] [ip:port]
- user 仓库用户名
- password 仓库密码
- ip:port为仓库地址
2、拉取镜像
sudo docker pull [image_name]
四、dockerfile编写
在项目目录下创建Dockerfile
文件
1、RUN
RUN
指令是用来执行命令行命令的。RUN
指令的格式有两种:
- shell 格式:
RUN <命令>
,就像直接在命令行中输入命令一样。
RUN java -jar app.jar
- exec 格式:
RUN ["可执行文件", "参数1", "参数2"]
。
RUN ["java", "-jar", "app.jar"]
在 Dockerfile
中,每一个指令都会在镜像上建立一层,所以对于多个命令行,不要写多个 RUN
指令。
多个命令,在一个RUN中实现,使用 **&&
**连接起来
FROM ubuntu
RUN apt-get update \
&& apt-get install -y redis
2、COPY
COPY
指令用来将宿主的文件目录复制到镜像中。有两种格式:
COPY [--chown=<user>:<group>] <源路径>... <目标路径>
COPY app.jar /usr/src/
COPY [--chown=<user>:<group>] ["源路径1", ... "目标路径"]
COPY ["app.jar", "config.yml", "/usr/src"]
对于多个路径参数,最后一个为目标路径,其他都是源路径。目标路径
可以是绝对路径,也可以是相对于工作目录的路径(工作目录可以用 WORKDIR
来指定)。目标路径如果不存在,在复制文件前会先创建。
3、CMD
CMD
是容器启动命令,它指定了容器启动后要执行的程序。与 RUN
指令相似有两种形式:
- shell 格式:
CMD <命令>
CMD echo 'Hello, world!''
- exec 格式:
CMD ["可执行文件", "参数1", "参数2", ...]
CMD [ "sh", "-c", "echo 'Hello, world!'" ]
还有一种参数列表格式:CMD ["参数1", "参数2", ...]
。在指定了 ENTRYPOINT
指令后,可以用 CMD
指定参数。
在使用 CMD
时,程序必须以前台运行,Docker 不是虚拟机,容器没有后台服务的概念。如果使用 CMD
运行一个后台程序,那么容器在命令执行完就会退出。
CMD java -jar app.jar &
以上命令让 app.jar 在后台运行,容器启动后就会立刻退出。Docker 容器与守护线程很相似,当所有前台程序退出后,容器就会退出。
CMD
指定的命令可以在运行时替换,跟在镜像名称后面的参数将替换镜像中的 CMD
。
docker run app echo $HOME
以上命令运行容器时使用 echo $HOME
替换掉镜像中的启动命令。
4、ENV
ENV
指令用来设置环境变量,格式有两种:
ENV <key> <value
ENV <key1>=<value1> <key2>=<value2>
环境变量在后面的其它指令中可以通过 $key
来使用:
FROM ubuntu
ENV VERSION="8-jre"
RUN apt-get update \
&& apt-get install -y openjdk-$VERSION
...
5、ARG
ARG
指令指定构建参数,与 ENV
效果一样,都是设置环境变量。不同的是,ARG
设置的构建参数,在容器运行时不存在。
格式:ARG <key>[=<默认值>]
,可以指定默认值,也可以不指定。
FROM alpine
ARG NAME="Hello, Docker!"
RUN echo $NAME
CMD echo $NAME
对于以上 Dockerfile
,在构建时可以看到输出,但是在运行容器时没有输出。
ARG
设置的参数可以在构建命令中指定:docker build --build-arg <key>=<value>
。
6、VOLUME
VOLUME
指令用来定义匿名卷。
VOLUME <路径>
VOLUME ["路径1", "路径2", ...]
对于数据库类需要保持数据的应用,其文件应该保存于卷(volume)中,在 Dockerfile
中,可以事先将指定的目录挂载为匿名卷。
VOLUME /data
这里 /data
目录在容器运行时自动挂载为匿名卷,任何写入 /data
中的数据都不会记录到容器的存储层。在运行时可以覆盖这个挂载设置:
docker run -v dbdir:/data
以上命令将 dbdir
目录挂载到了 /data
,替换了 Dockerfile
中的挂载配置。
7、EXPOSE
EXPOSE
指令指定容器运行时暴露的端口。格式:EXPOSE <端口1> [<端口2> ...]
。
FROM ubuntu
EXPOSE 8080
RUN apt-get update \
&& apt-get install -y tomcat8
...
以上 Dockerfile
安装了 tomcat 应用,在运行容器时会暴露 8080 端口。
EXPOSE
只是指定了容器暴露的端口,并不会在宿主机进行端口映射。在使用 docker run -P
时,会自动随机映射 EXPOSE
指定的端口,也可以使用 -p
指定端口:docker run -p <宿主端口>:<容器端口>
。
8、WORKDIR
WORKDIR
指令指定工作目录,即指定当前目录,类似于 cd
命令,以后各层的当前目录都是 WORKDIR
指定的目录。如果目录不存在,会自动创建。格式:WORKDIR <目录路径>
。
不能把 Dockerfile
当成 Shell 脚本来写:
RUN cd /src/app
RUN java -jar app.jar
以上操作中第二行的工作目录并不是 /src/app
,两个指令不在同一层,第一个 RUN
指令的 cd
操作和第二个没有任何关系。因此要切换目录,应该使用 WORKDIR
来指定。
9、USER
USER
指令指定当前用户。与 WORKDIR
相似,会影响以后的层。USER
改变执行 RUN
、CMD
和 ENTRYPOINT
的用户。格式:USER <用户名>[:<用户组>]
。
USER
指定的用户和组必须是事先创建好的,否则无法切换。
# 添加用户
RUN groupadd -r redis \
&& useradd -r -g redis redis
USER redis
ENTRYPOINT ["reids-server"]
10、ONBUILD
ONBUILD
指令后面跟的是其它指令,它在当前镜像构建时不会被执行,只有以当前镜像为基础镜像去构建下一级镜像时才会被执行。格式:ONBUILD <其它指令>
。
FROM openjdk:8-jre-alpine
WORKDIR /app
ONBUILD COPY ./app.jar /app
...
这个 Dockerfile
在构建时不会执行 ONBUILD
。
FROM my-jre
...
假设之前构建的镜像名是 my-jre,以上 Dockerfile
构建镜像时,原来的 ONBUILD
将执行。
11、ENTRYPOINT
ENTRYPOINT
的格式与 CMD
一样有两种格式。
它和 CMD
一样都是指定容器启动的程序和参数,但稍有区别。当指定了 ENTRYPOINT
后,CMD
的内容将作为参数加到 ENTRYPOINT
后面。
也就是变成了:
<ENTRYPOINT> "<CMD>"
ENTRYPOINT
可以让镜像像命令一样使用,当仅仅使用 CMD
时,run
命令中镜像名后面的参数会替换 CMD
的内容。使用 ENTRYPOINT
后,这些参数将附加到原来命令的后面。
FROM alpine
ENTRYPOINT [ "ls" ]
使用以上 Dockerfile
构建的镜像运行容器:
docker run app -al
-al
参数将附加到 ENTRYPOINT
指定的命令后面,当容器启动时执行的是 ls -al
。
12、Dockerfile案例
FROM ubuntu:18.04 # 从仓库拉取一个Ubuntu 18.04的进项
WORKDIR /root # 容器中的工作目录
RUN apt-get update && \
apt-get install -y vim python3 python3-pip language-pack-zh* mysql-client # 容器中安装环境
RUN python3 -m pip install -r /root/requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/ # 容器中安装项目依赖
五、docker安装MySQL
1、下载指定版本镜像
docker pull mysql:8.0.21
2、启动容器
cd /home/up/docker_test # 进入挂载文件
docker run -p 3307:3306 --name mysql-8 -v $PWD/mysql_data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=hf1234 -d mysql:8.0.21 # $PWD 表示当前目录下
-p:表示端口映射,冒号左面的是宿主机的端口,而右侧则表示的是MySQL容器内的端口
--name:给MySQL容器取的名字
-d:表示后台运行
-e MYSQL_ROOT_PASSWORD:设置root用户密码
-v:表示挂载路径,冒号左面的表示宿主机的挂载目录,冒号右边则表示容器内部的路径。
3、进入容器
docker exec -it mysql-8 bash
msyql -uroot -p # 登录数据库
可能出现的错误:
4、可设置远程访问
use mysql;
select host,user from user;
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '<root_password>';
flush privileges;
六、docker容器间通信
如果在同一个主机上,MySQL为一个容器,django项目为另一个容器,那么就需要两个容器能够互相访问
1、案例
django应用容器,MySQL容器
cd /home/xx/docker_recoder # 宿主机挂载目录
xx@xx: /home/xx/docker_recoder: $ docker run -d --name mysqlserver -v $PWD/mysql/mysql_data:/var/lib/mysql -p3307:3306 mysql:latest # 运行MySQL容器
xx@xx: /home/xx/docker_recoder: $ docker run -d --name django-web -v $PWD/web/logs:/root/web/logs -p8001:8000 django_web:1.0 # 启动django应用容器,$PWD表示当前目录
注意事项
- 在django中MySQL的host用MySQL容器内部的 ip,port为容器内部的port(3306),
- 可通过
docker inspect mysqlserver
查看容器信息,无需安装工具 - 可通过进入容器后,
ifconfig
获取容器ip,但是需要安装ifconfig,如下第三点所示安装方法
- 查看容器间能否通信,可以
ping <container ip>
,能ping通说明能通信
ping 172.17.0.3
- 如果无
ping
、ifconfig
等工具
# 安装ping
apt-get install inetutils-ping
# 安装ifconfig
apt-get install net-tools
2、实现同主机容器间通信
在安装好docker后,docker将创建一个linux网桥docker0,它在内核层连通了其他的物理或虚拟网卡,也就是所有容器和本地主机都放到同一个物理网络。docker还会给我们创建三个网络:bridge
/host
/none
,网桥bridge模式是在实际项目中常用的,在没有指定相关网络的情况下,容器都会连接到默认的bridge网络。可以通过 --network
docker network ls # 查看宿主机中所有的docker网络
(1)link连接
默认的桥接网络支持使用端口映射和docker run --link
命令,实现容器间互相通信。该方法已经在官方文档中标识为不推荐使用。
(2)自定义bridge网络,实现容器间通信
从 Docker 1.10 版本开始,docker daemon 实现了一个内嵌的 DNS server,使容器可以直接通过“容器名”通信。使用默认的bridge网络,不能通过DNS server实现通过容器名通信,但是使用自定义bridge网络可以做到通过容器名互相通信。
0)使用默认的网桥,即启动容器时,不指定--network
,此时可通过 ip进行ping
,但是不能通过容器名进行ping
进入容器,查看hosts,此时hosts中并没有其他容器的信息
docker exec -it contian-name bash
cat /etc/hosts
1)创建网桥
docker network create --driver=bridge mybridge
docker network create \
--driver=bridge \
--subnet=172.28.5.0/24 \
--ip-range=172.28.5.0/24 \
--gateway=172.28.5.1 \
mybridge
2)使用自定义网桥启动容器
通过--network
指定网桥
docker run --name name --network mybridge -p 8001:8000 image_id
3)查看容器网桥
docker network inspect mybridge
如图,两个容器mysql-test、django-test都绑在了该网桥
3、容器加入网桥的方式
1)启动容器时,通过--network
指定网桥
docker run --network
2)启动容器后,加入网桥
docker run --name my-name # 不指定网桥
docker network connect my_bridge my-name # 通过 docker network connect 为已启动的容器添加网桥
七、docker化部署流程
docker pull mysql:8.0
拉取MySQL的镜像- 项目中编写
Dockerfile
,docker build -t image_name .
制作项目镜像 - 创建网桥,
docker network create --driver=bridge mybridge
- 启动容器
docker run -d --name mysql-1 --network mybridge -e MYSQL_ROOT_PASSWORD=123123 -v /home/xx/mysql_data:/var/lib/mysql -p 3307:3306 mysql:8.0
docker run --name django-test --network mybridge -p 8001:8000 django_test:latst
- 进入容器,可修改项目的配置,或者将配置文件通过
-v
挂载到宿主机
博客内容仅供参考,部分参考他人优秀博文,仅供学习使用