Dockerfile和docker-compose详解

在这里插入图片描述

Dockerfile和docker-compose详解

文章目录

    • Dockerfile和docker-compose详解
      • 一、Dockerfile
        • 1. Dockerfile简介
        • 2. 构建镜像
        • 3. Dockerfile命令
            • (1)FROM
            • (2)WORKDIR
            • (3)RUN
            • (4)COPY
            • (5)EXPOSE
            • (6)CMD
    • 二、docker-compose
        • 1.简介
        • 2.多服务实例
          • (1)文件准备
          • (2)启动服务
          • (3)访问服务
        • 3. docker-compose的service
          • (1)service和container
          • (2)service的广泛应用
        • 4. docker-compose的指令
          • (1)image
          • (2)build
          • (3)depends_on
          • (4)environment
          • (5)volume

一、Dockerfile

1. Dockerfile简介

Dockerfile是一个用来构建镜像的文本文件, 文本内容包含了一条条构建镜像所需的指令和说明。例如我们要在含python3的centos镜像基础上安装vim,可以这么写。

FROM centos:python3
RUN yum -y install vim

这里的FROM表示从哪个镜像开始构建,可以是本地已有的镜像,也可以是dockerhub或者私域的镜像。

2. 构建镜像

在Dockerfile文件的存放目录下, 执行构建动作

# 1. nginx表示镜像名称, v3表示版本
# 2. 最后的.表示Dockerfile相对终端执行环境的相对路径
docker build -t centos:python3 .  
3. Dockerfile命令
(1)FROM

定制的镜像都是基于FROM的镜像, 后续的操作都是基于该镜像做的操作

(2)WORKDIR

官方文档的说明,WORKDIR的作用是为RUN, COPY等指令设置工作目录,相当于cd到那个目录,然后执行对应的指令。如果没有设置WORKDIR,它会自动创建,默认是/,如果是从其他镜像开始构建的,那么WORKDIR就是其他镜像。

The WORKDIR instruction sets the working directory for any RUN, CMD, ENTRYPOINT, COPY and ADD instructions that follow it in the Dockerfile. If the WORKDIR doesn’t exist, it will be created even if it’s not used in any subsequent Dockerfile instruction.

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
输出就是/a/b/c
(3)RUN

用于执行后面跟着的命令行命令

RUN <命令行命令>   # 命令行命令 等同于在终端操作的shell命令

例如前面的

RUN yum -y install vim

注意,在RUN命令中有路径时,指的是容器外的相对路径,而不是容器内的路径,因为它此时还只是构建镜像。

(4)COPY

将宿主机的文件拷贝到镜像中。由于它是构建镜像时的命令,因此它会将文件写入到镜像中,只要是由该镜像创建的容器,都会有拷贝过去的文件,这是它和挂载的不同。

FROM centos:vim-python3
RUN yum -y install vim
COPY python/ /lkidti/
CMD python3 /lkidti/http_server.py
  • 源路径src:宿主机内的路径,是相对Dockerfile的路径,不能用绝对路径。例如写成/home/lkidti/python,这种写法是不对的,因为dockerfile会把它翻译成 dockerfile路径+/home/lkidti/python。

  • 目的路径dest:容器内的路径,用的是绝对路径,或者是相对workdir的路径。

(5)EXPOSE

暴露端口,这个命令的作用参见官方文档。

The EXPOSE instruction does not actually publish the port. It functions as a type of documentation between the person who builds the image and the person who runs the container, about which ports are intended to be published

expose命令的作用并不会去暴露端口,而是作为构建镜像的开发人员和运行容器的开发人员之间一个“接口文档”,构建镜像的开发人员告诉运行容器的开发人员,该镜像监听哪个端口。因为对于运行容器的开发人员来说,它可能接触不到源码,不清楚该镜像能暴露哪个端口,expose命令能帮助他了解到。例如redis镜像。

[lkidti@hecs-300320 ~]$ docker run -id redis:latest
Unable to find image 'redis:latest' locally
latest: Pulling from library/redis
c7ae2cc6d9d5d2fee1aefbea14014bb42806b45c60b7d6a1cf3313d5367ae895
[lkidti@hecs-300320 ~]$ docker ps
CONTAINER ID   IMAGE          COMMAND                   CREATED         STATUS         PORTS                                                  NAMES
c7ae2cc6d9d5   redis:latest   "docker-entrypoint.s…"   5 seconds ago   Up 3 seconds   6379/tcp                                               awesome_cori

它这里就暴露了6379端口,因此我们需要在运行的时候通过-p来做端口映射,来保证通过访问宿主机来访问容器。

(6)CMD

在镜像构建好后,用镜像启动容器时(docker run)会执行的命令。当在Dockerfile中写了CMD时,如果在用docker run或者docker-compose启动容器时,又再加了启动命令,此时执行的是docker run或者docker-compose的命令,如果没有加,执行的就是Dockerfile中的命令。

  • 例子1:docker run加了命令/bin/bash
[lkidti@hecs-300320 ~]$ docker run -id centos:python-vim /bin/bash
9a25fca7d79046bf693e95e2836744a5d973b12dc25adefe9b78e7e56e56df8f
[lkidti@hecs-300320 ~]$ docker ps
CONTAINER ID   IMAGE               COMMAND                   CREATED         STATUS         PORTS                                                  NAMES
9a25fca7d790   centos:python-vim   "/bin/bash"               4 seconds ago   Up 3 seconds                                                          nice_mendel
33d744b8729a   mysql:latest        "docker-entrypoint.s…"   8 hours ago     Up 8 hours     0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   mysql

例子2:docker run中不加命令

[lkidti@hecs-300320 ~]$ docker run -id centos:python-vim
dba629df688a0fb326d7e1c668fe4393673ca3f1789dd7a9e666fcd9344990d7
[lkidti@hecs-300320 ~]$ docker ps
CONTAINER ID   IMAGE               COMMAND                   CREATED         STATUS         PORTS                                                  NAMES
dba629df688a   centos:python-vim   "/bin/sh -c 'python3…"   5 seconds ago   Up 4 seconds                                                          vigorous_solomon
33d744b8729a   mysql:latest        "docker-entrypoint.s…"   8 hours ago     Up 8 hours     0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   mysql

二、docker-compose

1.简介

用于构建和启动多容器工具, 通过docker-compose.yml来配置项目需要的所有服务, 然后docker-compose up启动所有服务

2.多服务实例

参考官方文档https://docs.docker.com/compose/gettingstarted/

(1)文件准备

新建一个目录:

mkdir composetest
cd composetest

新建一个app.py文件

# composetest/app.py
import timeimport redis
from flask import Flask
​
app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)
​
def get_hit_count():retries = 5while True:try:return cache.incr('hits')except redis.exceptions.ConnectionError as exc:if retries == 0:raise excretries -= 1time.sleep(0.5)
​
@app.route('/')
def hello():count = get_hit_count()return 'Hello World! I have been seen {} times.\n'.format(count)

新建一个requirements.txt,里面包含如下内容

# composetest/requirements.txt
flask
redis

新建一个Dockerfile

# syntax=docker/dockerfile:1
FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["flask", "run"]

新建一个docker-compose.yml

services:web:build: .ports:- "8000:5000"redis:image: "redis:alpine"
(2)启动服务

docker compose up # 注意,最新版本可以不要中间的"-"

此时应该会看到两个服务都启动起来了

CONTAINER ID   IMAGE             COMMAND                  CREATED          STATUS          PORTS                                                  NAMES
b69ccfb85c03   composetest-web   "flask run"              12 minutes ago   Up 12 minutes   0.0.0.0:8000->5000/tcp, :::8000->5000/tcp              composetest-web-1
ea71df663f36   redis:alpine      "docker-entrypoint.s…"   12 minutes ago   Up 12 minutes   6379/tcp                                               composetest-redis-1
(3)访问服务

在服务器内部执行

curl http://127.0.0.1:5000

可以看到输出

Hello World! I have been seen 1 times.

由于是在服务器上部署,还可以在浏览器中访问http://121.36.104.55:8000/,也是一样的输出。注意,要开放8000端口。

3. docker-compose的service
(1)service和container

在上面的例子,web实际上指的是一个服务,而不是一个容器。参考https://stackoverflow.com/a/35585573/10844937

A service can be run by one or multiple containers. With docker you can handle containers and with docker-compose you can handle services.

service可以由一个或多个container组成。docker一般来操作container,docker-compose一般来操作service。可以在docker- compose中指定scale参数来指定container的个数,例如

services:web:build: .scale: 4redis:image: "redis:alpine"

此时会有4个container

➜  composetest git:(master) ✗ docker ps                  
CONTAINER ID   IMAGE             COMMAND                  CREATED          STATUS          PORTS      NAMES
f17412bbb248   composetest-web   "flask run"              15 seconds ago   Up 5 seconds    5000/tcp   composetest-web-4
ded649c4cec8   composetest-web   "flask run"              15 seconds ago   Up 5 seconds    5000/tcp   composetest-web-3
642b05b9c66e   composetest-web   "flask run"              15 seconds ago   Up 5 seconds    5000/tcp   composetest-web-2
7732ae7c78c8   composetest-web   "flask run"              16 seconds ago   Up 5 seconds    5000/tcp   composetest-web-1
1cf0b1c34972   redis:alpine      "docker-entrypoint.s…"   10 minutes ago   Up 10 minutes   6379/tcp   composetest-redis-1

在docker-compose中,必须有service name,而不必有container name,如果没有container name,那么container name=<当前工作路径名>,这里的sequence number是从1开始的。

(2)service的广泛应用

非常重要的一点: service name 可以广泛的被应用

在nginx中,可以看到proxy_pass http://web:8000;这样的表示式,这里的web就是指的service name

在django的settings中,可以看到数据的配置如下,这里的db指的也是service name

DATABASES = {'default': {'ENGINE': 'django.db.backends.postgresql','NAME': 'orthanc','HOST': 'db','PORT': 5432,'USER': 'lkidti','PASSWORD': '4a53e4f5c42fd5a31890860b204472c5'}
}
4. docker-compose的指令
(1)image

如果本地有镜像, 直接用本地镜像; 如果没有, 采用dockerhub的。

version: "3.7"
services:webapp:build:context: ./dir  # Dockerfile的路径dockerfile: Dockerfile-alternate  # Dockerfile的名字args:buildno: 1  # Dockerfile构建镜像时候的参数,在构建时候的环境变量
(2)build

build: 是指通过Dockerfile来构建。当一个yaml文件中,既有image又有build时,它的顺序如下:

首先看本地是否有镜像,如果有,用本地的镜像

本地如果没有,尝试从dockerhub拉。

如果dockerhub拉不到,则用build参数中指定的Dockerfile来构建镜像。

services:backend:image: awesome/databasebuild:context: backend  # 相对docker-compose的子目录dockerfile: ../backend.Dockerfile  # dockerfile文件名
(3)depends_on

告诉docker-compose当前服务启动之前先要把depends_on指定的服务启动起来才行

(4)environment

environment变量可以在构建镜像过程中,在Dockerfile中去使用。也可以在已构建好的镜像制作出的容器中使用,在容器的终端中输入env即可查找到所有的环境变量。可以用如下的python代码拿到具体的环境变量。

import os
os.environ.get('DEBUG')
(5)volume

docker的挂载主要有两种方式

  • bind mount(全路径的主机目录): 将主机的目录mount到container中,这种方式主机的目录路径必须为全路径,否则docker会将其当做volume处理。这种方式有一个不好的地方: windows和linux的目录结构不一样,那么此时我们是没法在不同的系统去写一个主机的目录来兼容的。

  • volume(非全路径的主机目录): volume和bind mount不同之处在于,volume的主机目录是被docker管理的,都在主机的/var/lib/docker/volumes目录下,这个目录的权限非常严格,即使是用sudo都不能打开(cd)。将my-volume挂载到container中的/mydata目录: docker run -it -v my-volume:/mydata alpine sh,它会在主机下创建/var/lib/docker/volumes/my-volume/_data目录,如果该目录不存在,那么docker会先创建然后再挂载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/454608.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MATLAB智能算法 - Immunity Algorithm免疫算法

Immunity Algorithm免疫算法 智能算法是路线规划、深度学习等等一系列领域所使用的优化算法&#xff0c;是算法进阶之路的必备之路。 前言&#xff1a;本文主要围绕解决TSP旅行商问题展开&#xff0c;对于机器人的路线规划以及非线性方程求解的问题等解决方案 对于一些其他智能…

Rust的泛型基础与实践

什么是泛型&#xff1f; 想象一下&#xff0c;我们想定义一个函数&#xff0c;它可以用来计算任意类型数据的最大值。如果我们只考虑整数&#xff0c;我们可以这样写&#xff1a; fn max(a: i32, b: i32) -> i32 {if a > b {a} else {b} }但是&#xff0c;如果我们还想…

【每日刷题】Day142

【每日刷题】Day142 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 1219. 黄金矿工 - 力扣&#xff08;LeetCode&#xff09; 2. 980. 不同路径 III - 力扣&#xff0…

C++20中头文件ranges的使用

<ranges>是C20中新增加的头文件&#xff0c;提供了一组与范围(ranges)相关的功能&#xff0c;此头文件是ranges库的一部分。包括&#xff1a; 1.concepts: (1).std::ranges::range:指定类型为range&#xff0c;即它提供开始迭代器和结束标记(it provides a begin iterato…

MP9928模块分析

MP9928 是一款高性能的同步降压 DC/DC 转换器控制器 IC&#xff0c;具有宽输入范围。以下是其操作和关键特性的总结&#xff1a; 概述 电流模式控制&#xff1a;MP9928 使用电流模式、可编程开关频率控制架构&#xff0c;通过外部 N 沟道 MOSFET 开关来调节输出电压。 反馈和…

PRCV2024:可信AI向善发展与智能文档加速构建

目录 0 写在前面1 GAI时代的挑战&#xff1a;图像内容安全1.1 图像篡改与对抗攻击1.2 生成式图像鉴别1.3 人脸鉴伪模型体验1.4 助力可信AI向善发展 2 GAI时代的机遇&#xff1a;大模型加速器2.1 TextIn大模型加速器2.2 通用文档解析2.3 文本向量模型 3 总结 0 写在前面 中国模…

认识一下:__asm { int 80h; LINUX - sys_fork }

这行代码 __asm { int 80h; LINUX - sys_fork } 使用了汇编语言的语法来直接调用 Linux 系统调用 fork。下面是对这行代码的详细解析&#xff1a; 代码解析 __asm: 这是一个用于嵌入汇编代码的指令&#xff0c;通常在 C 或 C 代码中使用&#xff0c;允许开发者直接插入汇编语言…

信息安全系统设计第七周

文章目录 密码系统设计学习内容AI 对学习内容的总结&#xff08;1分&#xff09;要求总结 第10章&#xff1a;身份认证和PKI理论基础第11章&#xff1a;实战PKI对 AI 总结的反思与补充&#xff08;2分&#xff09;要求反思与补充 学习思维导图&#xff08;2分&#xff09;要求思…

Pytorch 实现图片分类

CNN 网络适用于图片识别&#xff0c;卷积神经网络主要用于图片的处理识别。卷积神经网络&#xff0c;包括一下几部分&#xff0c;输入层、卷积层、池化层、全链接层和输出层。 使用 CIFAR-10 进行训练&#xff0c; CIFAR-10 中图片尺寸为 32 * 32。卷积层通过卷积核移动进行计…

告别微信封号!学会这5招,让你的账号坚不可摧

在这个信息爆炸的时代&#xff0c;无论是工作沟通、社交互动还是获取信息&#xff0c;微信都扮演着极其重要的角色。但是&#xff0c;随着微信平台规则的日益严格&#xff0c;账号被封的风险也随之增加。今天&#xff0c;我们就来聊聊如何有效防止 微信被封&#xff0c;让你的账…

【RL Latest Tech】安全强化学习(Safe RL):理论、方法与应用

&#x1f4e2;本篇文章是博主强化学习&#xff08;RL&#xff09;领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对相关等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅…

Python | Leetcode Python题解之第486题预测赢家

题目&#xff1a; 题解&#xff1a; class Solution:def PredictTheWinner(self, nums: List[int]) -> bool:length len(nums)dp [0] * lengthfor i, num in enumerate(nums):dp[i] numfor i in range(length - 2, -1, -1):for j in range(i 1, length):dp[j] max(num…

uniapp结合uview-ui创建项目

准备工作&#xff1a; 下载HBuilderX;官网地址:HBuilderX-高效极客技巧 安装node.js;官网地址&#xff1a;Node.js — 在任何地方运行 JavaScript,下载所需版本&#xff0c;安装后配置好环境变量即可 方式一&#xff08;NPM安装方式&#xff09;&#xff1a; 1、打开开发者…

代码随想录-哈希表-两个数组的交集

题目与思路 这个题目可以用大小为1000的数组&#xff0c;因为限制了变量大小。我用的是set&#xff0c;感觉这个才是本意。 下面代码是用set实现的hash结构。先用set1存储nums1中的去重元素&#xff0c;然后用set2存储结果集 最后将set转为array用了两种方式&#xff0c;一是…

LINUX设备OTA时无法从HTTP服务器(TOMCAT)下载文件

疑难问题排查记录 问题 linux设备作为http客户端&#xff0c;执行OTA前先从HTTP服务器下载bin固件&#xff0c;测试nginx没有问题&#xff0c;nodejs编写的HTTP服务器也没有问题&#xff0c;而软件同事使用的Tomcat则无法成功下载。 排查经过 首先利用chrome浏览器测试下载…

WebGl 实现图片平移、缩放和旋转

1.图片平移 在WebGL中实现图片平移&#xff0c;可以通过修改顶点着色器中的顶点位置来实现。平移的基本思想是将每个顶点的位置向量沿着指定的方向&#xff08;通常是x轴和y轴&#xff09;进行平移。在顶点着色器中&#xff0c;可以通过添加或减去一个统一的偏移量&#xff08…

「AIGC」n8n AI Agent开源的工作流自动化工具

n8n AI Agent 是一个利用大型语言模型(LLMs)来设计和构建智能体(agents)的工具,这些智能体能够执行一系列复杂的任务,如理解指令、模仿类人推理,以及从用户命令中理解隐含意图。n8n AI Agent 的核心在于构建一系列提示(prompts),使 LLM 能够模拟自主行为。 传送门→ …

C++:stack 和 queue 的使用和模拟实现

使用 要注意&#xff0c;stack 和 queue 没有迭代器。 stack void teststack() {stack<int> st;st.push(1);st.push(2);st.push(3);st.push(4);st.push(5);cout << st.size() << endl;while (!st.empty()){cout << st.top() << " ";…

电机编码器

旋转式编码器 链接: 野火编码器 单圈&#xff0c;多圈绝对式编码器 在单圈绝对值编码器中&#xff0c;单圈并不表示编码器机械转动的圈数&#xff0c;而是指断电记忆的范围。实际上&#xff0c;机械转动是可以无限制地进行圈数的&#xff0c;但是断电记忆仅限于一圈的范围内…

构建后端为etcd的CoreDNS的容器集群(二)、下载最新的etcd容器镜像

在尝试获取etcd的容器的最新版本镜像时&#xff0c;使用latest作为tag取到的并非最新版本&#xff0c;本文尝试用实际最新版本的版本号进行pull&#xff0c;从而取到想的最新版etcd容器镜像。 一、用latest作为tag尝试下载最新etcd的镜像 1、下载镜像 [rootlocalhost opt]# …