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 前端部署运行 docker 前端安装部署_Dockerfile

  • 若未启动,则启动docker服务:
$ sudo systemctl start docker
  • 查看docker版本号验证
$ sudo docker -v

docker 前端部署运行 docker 前端安装部署_docker 前端部署运行_02

二、docker仓库配置

1、设置公有仓库

  • 修改仓库配置文件
$ vim /etc/docker/daemon.json

docker 前端部署运行 docker 前端安装部署_docker 前端部署运行_03

{
  "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 改变执行 RUNCMDENTRYPOINT 的用户。格式: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			# 登录数据库

可能出现的错误:

docker 前端部署运行 docker 前端安装部署_docker_04

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容器内部的 ipport为容器内部的port(3306)
  • 可通过docker inspect mysqlserver查看容器信息,无需安装工具
  • 可通过进入容器后,ifconfig获取容器ip,但是需要安装ifconfig,如下第三点所示安装方法

docker 前端部署运行 docker 前端安装部署_Dockerfile_05

docker 前端部署运行 docker 前端安装部署_mysql_06

  • 查看容器间能否通信,可以ping <container ip>,能ping通说明能通信
ping 172.17.0.3
  • 如果无pingifconfig等工具
# 安装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网络

docker 前端部署运行 docker 前端安装部署_mysql_07

(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

docker 前端部署运行 docker 前端安装部署_Dockerfile_08

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都绑在了该网桥

docker 前端部署运行 docker 前端安装部署_docker_09

3、容器加入网桥的方式

1)启动容器时,通过--network指定网桥

docker run --network

2)启动容器后,加入网桥

docker run  --name my-name    # 不指定网桥
docker network connect my_bridge my-name		 # 通过 docker network connect 为已启动的容器添加网桥

七、docker化部署流程

  1. docker pull mysql:8.0拉取MySQL的镜像
  2. 项目中编写Dockerfiledocker build -t image_name .制作项目镜像
  3. 创建网桥,docker network create --driver=bridge mybridge
  4. 启动容器
    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.0docker run --name django-test --network mybridge -p 8001:8000 django_test:latst
  5. 进入容器,可修改项目的配置,或者将配置文件通过-v挂载到宿主机

博客内容仅供参考,部分参考他人优秀博文,仅供学习使用