前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >详解Docker——你需要知道的Docker进阶知识五

详解Docker——你需要知道的Docker进阶知识五

作者头像
云原生
发布2021-05-31 10:59:52
8840
发布2021-05-31 10:59:52
举报
文章被收录于专栏:云原生实践

Dockerfile

Dockerfile 是一个文本文件,其中包含了构建 Docker 镜像需要执行的命令序列。使用 docker build 命令从 Dockerfile 中读取指令来构建镜像。

上下文

构建镜像时,该过程的第一件事是将 Dockerfile 文件所在目录下的所有内容发送给 Docker 守护进程。所以大多数情况下,最好创建一个新的目录,在其中保存 Dockerfile,以及构建镜像所需的其它文件。Dockerfile 文件所在目录也被称为构建上下文(context)。

使用 FROM 指令指定一个基础镜像,后续指令将在此镜像基础上运行:

代码语言:javascript
复制
FROM ubuntu:14.04

在 Dockerfile 中可以指定一个用户,后续的 RUNCMD 以及 ENTRYPOINT 指令都会使用该用户身份去执行,该用户必须已存在。

代码语言:javascript
复制
USER soundhearer

除了指定用户之外,还可以使用 WORKDIR 指定当前工作目录(CWD), RUNCMDCOPYADD 指令将在指定的工作目录中执行。

代码语言:javascript
复制
WORKDIR /

RUN 指令用于执行命令,该指令有两种形式:

  • RUN,在 shell 中执行命令 command,一般默认的 shell/bin/sh
  • RUN["executable","param1","param2",...],运行可执行程序 executable,可以指定程序需要的命令行参数。

例如我们执行更新命令:

代码语言:javascript
复制
RUN apt-get update

CMD 的使用方式跟 RUN 类似,不过在一个 Dockerfile 文件中只能有一个 CMD 指令,如果有多个,则只有最后一个会生效。该指令指定了启动容器时要执行的命令,例如:

代码语言:javascript
复制
CMD echo "hello soundhearer"

可以在 docker run 时指定命令来覆盖默认的 CMD 命令,比如 docker run image echo"hello shiyanlou"

CMD 指令还有一种特殊用法。在 Dockerfile 中,如果使用 ENTRYPOINT 指令指定了入口命令,则 CMD 指令的内容会作为 ENTRYPOINT 指令的参数:

代码语言:javascript
复制
CMD ["param1", "param2"]

ENTRYPOINT 指令会覆盖 CMD 指令作为容器运行时的默认指令,并且该指令不会被 docker run 时指定的指令覆盖,如下示例:

代码语言:javascript
复制
FROM ubuntu:latest
ENTRYPOINT ["ls", "-a"]
CMD ["-l"]

上述文件构建出来的镜像,使用 docker run image 等同于 docker run image ls-a-l。使用 docker run image-i-s 等同于 docker run image ls-a-i-s。即 CMD 指令的值会被当作 ENTRYPOINT 指令的参数附加到 ENTRYPOINT 指令的后面,只有 CMD 指令可以被覆盖。

COPY和ADD

COPY 和 ADD 都用于将构建上下文中的文件,目录等复制到镜像中。使用方式如下:

代码语言:javascript
复制
ADD <src>... <dest>
ADD ["<SRC>",... "<dest>"]

COPY <src>... <dest>
COPY ["<src>",... "<dest>"]

`` 可以指定多个,但是其路径不能超出构建上下文范围,即必须在 Dockerfile 同级或子目录中。

不需要预先存在,不存在时会自动创建,如果使用相对路径,则 为相对于工作目录的路径。

COPY 和 ADD 的不同之处在于,ADD 可以添加远程文件,并且 `` 可以是 gzip 或 tar 等格式的压缩文件,添加时会自动进行解压。

ENV

ENV 指令用于设置环境变量:

代码语言:javascript
复制
ENV <key> <value>
ENV <key>=<value> <key>=<value>...

VOLUME

VOLUME 指令指定要创建的挂载路径,在容器运行时,将为每个挂载路径创建一个匿名卷并挂载上去:

代码语言:javascript
复制
VOLUME /data1 /data2

上述指令将会在容器运行时,创建两个匿名卷,并分别挂载到容器中的 /data1 和 /data2 路径。

EXPOSE

EXPOSE 用来暴露容器运行时会监听的端口,它只是一种声明,让外部能够知道容器内部的服务端口。可以在运行容器时通过 -p 选项来绑定容器监听端口到宿主机端口,这些监听端口不一定需要通过 EXPOSE 暴露。当使用 -P(大写)选项时会自动绑定所有暴露出来的端口。

代码语言:javascript
复制
EXPOSE port

从Dockerfile创建镜像

学习了上面这些常见的 Dockerfile 指令之后,可以使用这些指令来构建一个镜像。如下所示,构建一个提供 ssh 服务的镜像:

代码语言:javascript
复制
#cd /Docker-Ser/Dockerfile/centos-ssh
#vi Dockerfile
#生成的新镜像以centos镜像为基础
FROM centos
#指定作者信息
MAINTAINER soundhearer
# 安装openssh-server
RUN yum -y install openssh-server
RUN mkdir /var/run/sshd
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
#指定root密码
RUN /bin/echo 'root:123456'|chpasswd
RUN /bin/sed -i 's/.*session.*required.*pam_loginuid.so.*/session optional pam_loginuid.so/g' /etc/pam.d/sshd
RUN /bin/echo -e "LANG=\"en_US.UTF-8\"" > /etc/default/local
EXPOSE 22
CMD /usr/sbin/sshd -D

构建镜像

代码语言:javascript
复制
[root@VM_0_17_centos dockerfile]# docker build -t 5588/centos-ssh:v1.0.0 .
Sending build context to Docker daemon  14.85kB
Step 1/11 : FROM centos
 ---> 470671670cac
Step 2/11 : MAINTAINER soundhearer
 ---> Running in d5705e869a7e
Removing intermediate container d5705e869a7e
 ---> 76f3b6fa1597
Step 3/11 : RUN yum -y install openssh-server
 ---> Running in dcd4af79f6c1

查看镜像

代码语言:javascript
复制
[root@VM_0_17_centos dockerfile]# docker images
REPOSITORY                                          TAG                 IMAGE ID            CREATED             SIZE
5588/centos-ssh                                     v1.0.0              c16cedf7052c        2 minutes ago       278MB

启动容器

代码语言:javascript
复制
[root@VM_0_17_centos dockerfile]# docker run -itd -p 10022:22 --name test_centos_1 5588/centos-ssh:v1.0.0
ae638dff422529144e0066a98611a96ea51cd1469aa8007a503ed8b53ab62d22
[root@VM_0_17_centos dockerfile]#

查看已经启动的容器

代码语言:javascript
复制
[root@VM_0_17_centos dockerfile]# docker ps
CONTAINER ID        IMAGE                    COMMAND                  CREATED             STATUS              PORTS                   NAMES
ae638dff4225        5588/centos-ssh:v1.0.0   "/bin/sh -c '/usr/sb…"   51 seconds ago      Up 50 seconds       0.0.0.0:10022->22/tcp   test_centos_1

测试远程登录

代码语言:javascript
复制
[root@VM_0_17_centos dockerfile]# ssh -p10022 127.0.0.1
root@127.0.0.1's password:
[root@ae638dff4225 ~]#

Docker Compose

Compose

Compose 是运行由多个容器组成的 Docker 应用的工具,使用 Compose 可以一次启动一组有关联的服务,每个服务由来自同一镜像的单个或多个容器组成。

Service

在复杂应用中,应用一般由多个服务(service)组成,例如一个网站后台通常包含 Web 服务、数据库服务、缓存服务、消息队列服务等。

使用步骤

使用 Compose 的步骤如下:

  1. 定义和构建组成应用的各个服务的镜像,主要是编写各个服务的 Dockerfile 文件
  2. 定义应用服务描述文件,主要是编写 docker-compose.yml 文件
  3. 启动应用

关于 docker-compose.yml 文件的详细格式可以参考 官方文档。

目前有三种版本的 Compose 文件格式:

  1. version 1: 最早的版本使用传统格式,将在未来弃用
  2. version 2: 现在使用最多的文件格式
  3. version 3: 最新版本,旨在使得 Compose 和已被集成到 Docker Engine 中的 swarm mode 互相兼容。
安装

下载 docker-compose-Linux-x86_64

下载成功后,为了方便使用,可以将其添加到 PATH 路径下

代码语言:javascript
复制
sudo mv docker-compose-Linux-x86_64 /usr/local/bin/docker-compos
sudo chmod +x /usr/local/bin/docker-compose

执行完成后,就能够在终端下直接使用 docker-compose 命令了:

代码语言:javascript
复制
[root@VM_0_17_centos dockerfile]# docker-compose --help
Define and run multi-container applications with Docker.

Usage:
  docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...]
  docker-compose -h|--help
实例

接下来我们将创建一个 Web 应用,该应用包含两个容器:

  1. web 容器:提供 web 服务,该服务需要连接后端的 redis 服务
  2. redis 容器:提供 redis 服务

项目目录结构如下:

代码语言:javascript
复制
app
|----web
|     |----web.py
|     |----requirements.txt
|     |----Dockerfile
|
|----docker-compose.yml

首先编辑 app/web/web.py 文件,写入下面的内容:

代码语言:javascript
复制
from flask import Flask
from redis import Redis

app = Flask(__name__)
redis = Redis(host='redis', port=6379)

@app.route('/')
def hello():
    redis.incr('number')
    return 'Hello Docker! # %s' % redis.get('number')

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=80, debug=True)

上述代码创建了一个简单的 Web 应用。该应用会连接 redis 服务,在访问 / 页面时,自动将变量 number 加 1。

编辑 app/web/requirements.txt 文件,输入如下内容:

代码语言:javascript
复制
flask==0.10
redis==2.10.3

requirements.txt 文件存放了 Web 应用依赖的第三方库包的名称和版本信息。

编辑 app/web/Dockerfile 文件,添加如下内容

代码语言:javascript
复制
FROM python:2.7
COPY ./ /web/
WORKDIR /web
RUN pip install -r requirements.txt
CMD python web.py

上述 Dockerfile 定义了 Web 应用镜像,该镜像基于 python:2.7 基础镜像,在其基础上安装了应用依赖的库包,并通过 CMD 指令指定了应用的启动命令。

编辑 app/docker-compose.yml 文件:

代码语言:javascript
复制
services:
  redis:
    image: redis:3.2
  web:
    build:
      context: /home/shiyanlou/app/web
    depends_on:
    - redis
    ports:
    - 8001:80/tcp
    volumes:
    - /home/shiyanlou/app/web:/web:rw
version: '3.0'

docker-compose.yml 文件定义了两个服务,分别为 webredis 服务,并且配置了 web 服务的端口映射和挂载目录。depends_on 定义了依赖关系,被依赖的服会先启动。

进入 app 目录,执行 docker-compose up 命令来启动应用:

代码语言:javascript
复制
[root@VM_0_17_centos app]# docker-compose up
Building web
Step 1/5 : FROM python:2.7
 ---> fbc983cb5352
Step 2/5 : COPY ./ /web/
 ---> 10bdacc94674
Step 3/5 : WORKDIR /web
 ---> Running in 7ff982241c92
Removing intermediate container 7ff982241c92
 ---> 0a37af3e9713
Step 4/5 : RUN pip install -r requirements.txt
 ---> Running in 9832ab0165d1
DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support
Collecting flask==0.10
  Downloading Flask-0.10.tar.gz (544 kB)
Collecting redis==2.10.3
  Downloading redis-2.10.3.tar.gz (86 kB)
Collecting Werkzeug>=0.7
  Downloading Werkzeug-1.0.0-py2.py3-none-any.whl (298 kB)

Collecting Jinja2>=2.4
  Downloading Jinja2-2.11.1-py2.py3-none-any.whl (126 kB)
Collecting itsdangerous>=0.21
  Downloading itsdangerous-1.1.0-py2.py3-none-any.whl (16 kB)
Collecting MarkupSafe>=0.23
  Downloading MarkupSafe-1.1.1-cp27-cp27mu-manylinux1_x86_64.whl (24 kB)
Building wheels for collected packages: flask, redis
  Building wheel for flask (setup.py): started
  Building wheel for flask (setup.py): finished with status 'done'
  Created wheel for flask: filename=Flask-0.10-py2-none-any.whl size=115528 sha256=967ce1269d455054b3713a87985eeceda84b437ff0c2d0ba8855bb813daf9c10
  Stored in directory: /root/.cache/pip/wheels/75/15/2c/b14930624e0a52fdd754537b216da52d96b79dd5d14966abb7
  Building wheel for redis (setup.py): started
  Building wheel for redis (setup.py): finished with status 'done'
  Created wheel for redis: filename=redis-2.10.3-py2-none-any.whl size=50695 sha256=9741ffb0196e0dc9d1818811a48f206aff9c53699dfe822e1b0f9591f72db9e8
  Stored in directory: /root/.cache/pip/wheels/12/ce/01/1aba4866d936f9a08aeb59a573b188c17daea0da2537c68dea
Successfully built flask redis
Installing collected packages: Werkzeug, MarkupSafe, Jinja2, itsdangerous, flask, redis
Successfully installed Jinja2-2.11.1 MarkupSafe-1.1.1 Werkzeug-1.0.0 flask-0.10 itsdangerous-1.1.0 redis-2.10.3
Removing intermediate container 9832ab0165d1
 ---> f12bc5dc1aac
Step 5/5 : CMD python web.py
 ---> Running in aec73ed63ab6
Removing intermediate container aec73ed63ab6
 ---> 228792f96283
Successfully built 228792f96283
Successfully tagged app_web:latest
WARNING: Image for service web was built because it did not already exist. To rebuild this image you must use `docker-compose build` 
Creating app_redis_1 ... done
Creating app_redis_1 ... 
Creating app_web_1   ... done
Attaching to app_redis_1, app_web_1
redis_1  | 1:C 14 Mar 13:54:22.030 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis_1  |                 _._
redis_1  |            _.-``__ ''-._
redis_1  |       _.-``    `.  `_.  ''-._           Redis 3.2.12 (00000000/0) 64 bit
redis_1  |   .-`` .-```.  ```\/    _.,_ ''-._
redis_1  |  (    '      ,       .-`  | `,    )     Running in standalone mode
redis_1  |  |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
redis_1  |  |    `-._   `._    /     _.-'    |     PID: 1
redis_1  |   `-._    `-._  `-./  _.-'    _.-'                                   
redis_1  |  |`-._`-._    `-.__.-'    _.-'_.-'|
redis_1  |  |    `-._`-._        _.-'_.-'    |           http://redis.io
redis_1  |   `-._    `-._`-.__.-'_.-'    _.-'
redis_1  |  |`-._`-._    `-.__.-'    _.-'_.-'|                                  
redis_1  |  |    `-._`-._        _.-'_.-'    |                                  
redis_1  |   `-._    `-._`-.__.-'_.-'    _.-'
redis_1  |       `-._    `-.__.-'    _.-'
redis_1  |           `-._        _.-'
redis_1  |               `-.__.-'                                               
redis_1  | 
redis_1  | 1:M 14 Mar 13:54:22.033 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
redis_1  | 1:M 14 Mar 13:54:22.033 # Server started, Redis version 3.2.12
redis_1  | 1:M 14 Mar 13:54:22.033 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
redis_1  | 1:M 14 Mar 13:54:22.033 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
redis_1  | 1:M 14 Mar 13:54:22.033 * The server is now ready to accept connections on port 6379
web_1    |  * Running on http://0.0.0.0:80/ (Press CTRL+C to quit)
web_1    |  * Restarting with stat
web_1    |  * Debugger is active!
web_1    |  * Debugger PIN: 764-159-950
web_1    | 116.30.196.114 - - [14/Mar/2020 13:58:04] "GET / HTTP/1.1" 200 -
web_1    | 116.30.196.114 - - [14/Mar/2020 13:58:05] "GET /favicon.ico HTTP/1.1" 404 -
web_1    |  * Detected change in '/web/web.py', reloading
web_1    |  * Restarting with stat
web_1    |  * Debugger is active!
web_1    |  * Debugger PIN: 764-159-950

启动成功后,就可以打开网址 127.0.0.1:8001 来访问 Web 应用了。

另外一些命令:

代码语言:javascript
复制
# 后台运行应用:
docker-compose up -d
# 查看容器
docker-compose ps
# 查看镜像
docker-compose images
# 停止并删除应用,相关容器也会一并删除
docker-compose down
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-03-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 云原生 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Dockerfile
    • 上下文
      • COPY和ADD
        • ENV
          • VOLUME
            • EXPOSE
              • Compose
              • Service
              • 使用步骤
              • 安装
              • 实例
          • 从Dockerfile创建镜像
          • Docker Compose
          相关产品与服务
          容器镜像服务
          容器镜像服务(Tencent Container Registry,TCR)为您提供安全独享、高性能的容器镜像托管分发服务。您可同时在全球多个地域创建独享实例,以实现容器镜像的就近拉取,降低拉取时间,节约带宽成本。TCR 提供细颗粒度的权限管理及访问控制,保障您的数据安全。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档