在docker中运行web服务
1 ) 以nginx为例运行一个web服务
- 以nginx为例,如果要运行nginx就要有一个nginx镜像
- 在hub.docker.com中搜索nginx镜像,可以查看到有很多版本,我们找到一个基于alpine的版本(因为体积小,最新的体积会很大)
- $
docker pull nginx:alpine
此时我们下载好了基于alpine制作的nginx镜像 - 如果运行这个容器:$
docker run --rm nginx:alpine
,那么会卡住,因为nginx会作为一直提供服务 - 我们重新以后台服务的方式来运行我们的nginx, $
docker run -d --rm nginx:alpine
, 此时会不占用终端以后台服务方式运行
2 ) 运行docker服务并暴露端口
- 我们检查下现有的docker容器:$
docker ps
可以看到这个nginx服务占用了80端口提供服务 - 如果直接访问物理机的ip地址(默认80端口),是无法访问的,因为在容器里是一个封闭的环境, 而我们当前机器上并没有打开80端口
- 容器和物理机之间,两者是隔离开的,我们先把这个nginx服务给结束掉:$
docker kill nginx对应的容器ID
- 我们需要把nginx暴露的端口映射到物理机上, $
docker run -d --rm -P nginx:alpine
, 注意这里是大写的P选项 - 再次查看容器, $
docker ps
, 发现输出内容, 举例:0.0.0.0:32768->80/tcp
, 物理机上的32768端口映射到了docker容器的80端口 - 我们通过访问
物理机ip:32768
即可访问docker上的容器, 我们使用-P
选项的意义就是让物理机上一个没有使用的端口和docker容器上的一个端口做映射 - 但是这样同样存在一个问题,当docker容器重新运行后,端口可能就不是32768了,可能是别的了
- 如果是这样,没有一个固定的端口,我们就没法对外提供一个稳定的服务, 我们在实际应用中会使用另外一个选项
-p
,此处p是小写,我们可以自己指定端口 - 即:$
docker run -d --rm -p 8080:80 nginx:alpine
, 我们将物理机的8080端口绑定容器的80端口,这样的话就不会发生错乱的情况了 - 容器与容器之间的端口互不影响,它们之间都是隔离开的
- 我们查询docker容器可以使用
-q
的方式, 如:$docker ps -q
, 输出运行容器的ID列表 - 我们就可以通过 $
docker kill $(docker ps -q)
将所有运行中的容器全部关闭
构建自己的docker镜像
- 在docker中使用$
docker build
来构建一个docker镜像 - 在构建镜像前,我们需要先编写dockerfile文件来构建新的镜像
- 查阅docker的官方文档: https://docs.docker.com/engine/reference/builder/
- 查看右侧几个主要的命令:
FROM
、RUN
、CMD
、LABEL
、COPY
、WORKDIR
FROM
: 表示指定基础镜像RUN
: 在构建过程中需要执行的命令CMD
: 用于容器启动时需要执行的命令LABEL
: 标签,用于添加扩展的信息到镜像中, 如版本信息, 维护者信息等COPY
: 用于将文件拷贝到镜像之中WORKDIR
: 用于设置命令的工作目录- 我们编辑一个Dockerfile, $
vi Dockerfile
# 基于ubuntu,体积较大 # FROM ubuntu:16.04 FROM alpine LABEL version="1.0" LABEL description="my image" # 基于ubuntu的安装命令 # RUN apt update && apt -y install python3 # 基于alpine的安装命令, 尽量把所有命令都写到一起, 使用&&来连接, 避免多余的命令分层 RUN apk update && apk add python3 # 将当前目录下的所有文件拷贝到容器里的code目录,. 代表当前目录 COPY . /code # 指定工作目录 WORKDIR /code # 指定容器启动后将要执行的命令 CMD ["python3", "app.py"]
- 在同一目录下, 我们编写一个python文件
app.py
print("Hello Python")
- 开始构建一个新的镜像, $
docker build -t myapp .
-t
是--tag
的缩写.
是当前目录, dockerfile就在当前目录
- 构建完毕后, 可以通过 $
docker images
来查看,看到多了一个镜像myapp
- 我们开始运行这个镜像, $
docker run --rm myapp
, 输出Hello Python
- 在通过镜像启动容器的时候,有时候会在后面跟上一个命令,如: $
docker run --rm myapp echo hi
- 这里
echo hi
等价于在dockerfile中的CMD中的内容,并且会覆盖CMD中的命令 - 此时会输出
hi
,而非Hello Python
- 这里
- 在已经构建好的镜像中,查看详细信息 $
docker inspect myapp:latest
, 可以查看到镜像中更多的详细信息"Labels" : { "description" : "my image", "version": "1.0" }, "Cmd" : [ "python3", "app.py" ], "WorkingDir": "/code", # ... # 不再列举
- 在构建我们镜像的时候,最好使用默认的
Dockerfile
, 如果不这样做, 在docker build
的时候需要使用--file
来指定文件名