首页
留言板
推荐
Allen知识库
Search
1
VMware vSphere系列教程-部署DC/DHCP/DNS(五)
21 阅读
2
最强链路监控系统推荐Pinpoint
21 阅读
3
PC新时代开启! DDR5内存标准正式发布
19 阅读
4
Ansible系列教程-常用模块(二)
13 阅读
5
将物理机迁移到VMware虚拟机(P2V)
13 阅读
VMware
vCloud
Horizon
vSphere
NSX
运维相关
Docker
Network
Zabbix
Ansible
Python
Microsoft
Mysql
Linux
Windows Server
登录
/
注册
Search
标签搜索
ansible
docker
zabbix
chatgpt
windows模板
linux模板
模板
k3
lede
openwrt
docker网络配置
清理微信好友
python清理微信好友
grafana
监控交换机
实施教程
ansible安装
ubuntu
acrh17路由固件
访问宽带猫
Allen
累计撰写
134
篇文章
累计收到
0
条评论
首页
栏目
VMware
vCloud
Horizon
vSphere
NSX
运维相关
Docker
Network
Zabbix
Ansible
Python
Microsoft
Mysql
Linux
Windows Server
页面
留言板
推荐
Allen知识库
搜索到
11
篇与
的结果
2023-10-24
Docker搭建PHP+Nginx+Mysql环境
一、准备工作我们创建容器后,我们需要映射一些配置文件或网站程序文件到宿主机,所以我们创建一些文件夹来存放这些东西,我是创建了以下这些文件夹,你可以按照自己平时的习惯来创建。# mkdir -p /data/{mysql,nginx/{conf,rewrite},wwwroot,wwwlogs,source,download} 路径如下 /data /mysql 存放数据库备份 /nginx nginx配置文件 /conf /rewrite 伪静态 /wwwroot 网站文件 /wwwlogs 日志 /source 程序源代码 /download 下载目录二、部署环境2.1 部署MySQL运行容器# docker run \ -d \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD=12345678910 \ --name m_mysql mysql:5.7参数说明-d 让容器在后台运行-p 添加主机到容器的端口映射,前面是映射到本地的端口,后面是需要映射的端口-e 设置环境变量,MYSQL_ROOT_PASSWORD这里是设置mysql的root用户的初始密码--name 容器的名字,随便取,但是必须唯一在实际项目中,不建议用docker启动mysql,除非你能保证数据安全,否则很容易数据丢失,性能也不能最大化。进入容器docker exec -it m_mysql /bin/bash参数说明-t 在容器里生产一个伪终端-i 对容器内的标准输入 (STDIN) 进行交互开启Mysql远程连接这步你当然也可以不开启,可以使用ssh通道来连接,但是我这里记一笔。这里是5.7,注意了。a. 进入mysql# mysql -uroot -p12345678910 b. 选择数据库> use mysqlc. 开启远程连接> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'password' WITH GRANT OPTION; > FLUSH PRIVILEGES;d. 重启# service mysqld restart这样就可以通过公网IP连接了,如果还是不行,请看看防火墙(自身防火墙或者各大云服务商的安全组配置)。2.2 部署PHP1 运行容器# docker run \ -d \ -p 9000:9000 \ -v /data/wwwroot:/usr/share/nginx/html \ --link m_mysql:mysql \ --name m_phpfpm bitnami/php-fpm:8.0参数说明-d 让容器在后台运行-p 添加主机到容器的端口映射-v 添加目录映射–-name 容器的名字,随便取,但是必须唯一--link link 是在两个contain之间建立一种父子关系,父container中的web,可以得到子container db上的信息。通过link的方式创建容器,我们可以使用被Link容器的别名进行访问,而不是通过IP,解除了对IP的依赖。创建php文件<?php phpinfo(); ?>这时候你进php容器,在/usr/share/nginx/html文件夹中也能看到我们创建的index.php文件,因为我们设置了目录映射。这样我们就可以直接在宿主机直接更改,而不用进容器修改。2.3 部署Nginx运行容器docker run \ -d \ -p 80:80 \ --name m_nginx nginx:1.12成功后,我们可以进入容器看看,使用docker exec -it m_nginx /bin/bash进入容器,然后进入/etc/nginx/文件夹中,我们需要的挂载nginx.conf和conf.d文件夹中的配置文件,因为是我们平时需要频繁更改的配置,所以,我们将他们复制到宿主机上。退出命令行,不要使用exit,因为exit会让容器停止。这里使用ctrl + p + q来退出容器。然后使用docker cp操作复制出文件# docker cp m_nginx:/etc/nginx/nginx.conf /data/nginx # docker cp m_nginx:/etc/nginx/conf.d/default.conf /data/nginx/conf删除之前运行的Nginx容器# docker stop m_nginx && docker rm m_nginx重新运行Nginx容器# docker run \ -d \ -p 80:80 \ -v /data/wwwroot:/usr/share/nginx/html \ -v /data/nginx/nginx.conf:/etc/nginx/nginx.conf:ro \ -v /data/nginx/conf:/etc/nginx/conf.d \ -v /data/wwwlogs:/var/log/nginx \ --link m_phpfpm:phpfpm \ --name m_nginx nginx:1.12编辑配置文件修改/data/nginx/conf/default.conf,我的配置如下:server { listen 80; server_name _; #charset koi8-r; access_log /var/log/nginx/default_nginx.log main; location / { root /usr/share/nginx/html/default; index index.html index.htm; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # location ~ \.php$ { root /usr/share/nginx/html/default; fastcgi_pass phpfpm:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} }配置文件中的fastcgi_pass phpfpm:9000;,因为我们在启动容器的时候--link了phpfpm容器,所以这里直接填phpfpm,就能找到phpfpm的IP,当然你也可以不配置--link,那么你可以这样找到容器IP,再将IP填入。docker inspect 容器名或ID | grep "IPAddress"2.4 部署phpMyAdmin下载地址:https://www.phpmyadmin.net/解压到/data/wwwroot/default,并将文件夹重命名为phpMyAdmin配置phpMyAdmin 打开 libraries 目录下,找到config.sample.inc.php,改名为config.inc.php,用文本编辑器打开文件。在blowfish_secret中填入值,如:$cfg['blowfish_secret'] = 'sadsadsadasffdsadfsa'; /* YOU MUST FILL IN THIS FOR COOKIE AUTH! */ 在host中填入数据库的访问IP,这里我填的Mysql容器的内网IP,你也可以填外网IP试试。$cfg['Servers'][$i]['host'] = '172.17.0.2';保存退出访问http://IP/phpMyAdmin/index.php
2023年10月24日
7 阅读
0 评论
0 点赞
2021-02-10
Docker系列教程-Docker Compose(九)
简介Compose 项目是 Docker 官方的开源项目,负责实现对 Docker 容器集群的快速编排。从功能上看,跟 OpenStack 中的 Heat 十分类似。其代码目前在 https://github.com/docker/compose 上开源。Compose 定位是 「定义和运行多个 Docker 容器的应用(Defining and running multi-container Docker applications)」,其前身是开源项目 Fig。通过第一部分中的介绍,我们知道使用一个 Dockerfile 模板文件,可以让用户很方便的定义一个单独的应用容器。然而,在日常工作中,经常会碰到需要多个容器相互配合来完成某项任务的情况。例如要实现一个 Web 项目,除了 Web 服务容器本身,往往还需要再加上后端的数据库服务容器,甚至还包括负载均衡容器等。Compose 恰好满足了这样的需求。它允许用户通过一个单独的 docker-compose.yml 模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project)。Compose 中有两个重要的概念: 服务 (service):一个应用的容器,实际上可以包括若干运行相同镜像的容器实例。 项目 (project):由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义。 Compose 的默认管理对象是项目,通过子命令对项目中的一组容器进行便捷地生命周期管理。Compose 项目由 Python 编写,实现上调用了 Docker 服务提供的 API 来对容器进行管理。因此,只要所操作的平台支持 Docker API,就可以在其上利用 Compose 来进行编排管理。安装与卸载Compose 支持 Linux、macOS、Windows 10 三大平台。Compose 可以通过 Python 的包管理工具 pip 进行安装,也可以直接下载编译好的二进制文件使用,甚至能够直接在 Docker 容器中运行。Docker Desktop for Mac/Windows 自带 docker-compose 二进制文件,安装 Docker 之后可以直接使用。# docker-compose --version docker-compose version 1.27.4, build 40524192Linux 系统请使用以下介绍的方法安装。二进制包在 Linux 上的也安装十分简单,从 官方 GitHub Release 处直接下载编译好的二进制文件即可。例如,在 Linux 64 位系统上直接下载对应的二进制包。# curl -L https://github.com/docker/compose/releases/download/1.27.4/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose # 国内用户可以使用以下方式加快下载 # curl -L https://download.fastgit.org/docker/compose/releases/download/1.27.4/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose # chmod +x /usr/local/bin/docker-compose卸载如果是二进制包方式安装的,删除二进制文件即可。#rm /usr/local/bin/docker-compose使用首先介绍几个术语。 服务 (service):一个应用容器,实际上可以运行多个相同镜像的实例。 项目 (project):由一组关联的应用容器组成的一个完整业务单元。 可见,一个项目可以由多个服务(容器)关联而成,Compose 面向项目进行管理。场景最常见的项目是 web 网站,该项目应该包含 web 应用和缓存。下面我们用 Python 来建立一个能够记录页面访问次数的 web 网站。web 应用新建文件夹,在该目录中编写 app.py 文件from flask import Flask from redis import Redis app = Flask(__name__) redis = Redis(host='redis', port=6379) @app.route('/') def hello(): count = redis.incr('hits') return 'Hello World! 该页面已被访问 {} 次。\n'.format(count) if __name__ == "__main__": app.run(host="0.0.0.0", debug=True)Dockerfile编写 Dockerfile 文件,内容为FROM python:3.6-alpine ADD . /code WORKDIR /code RUN pip install redis flask CMD ["python", "app.py"]docker-compose.yml编写 docker-compose.yml 文件,这个是 Compose 使用的主模板文件。version: '3' services: web: build: . ports: - "5000:5000" redis: image: "redis:alpine"运行 compose 项目# docker-compose up此时访问本地 5000 端口,每次刷新页面,计数就会加 1。Compose 模板文件模板文件是使用 Compose 的核心,涉及到的指令关键字也比较多。但大家不用担心,这里面大部分指令跟 docker run 相关参数的含义都是类似的。默认的模板文件名称为 docker-compose.yml,格式为 YAML 格式。version: "3" services: webapp: image: examples/web ports: - "80:80" volumes: - "/data"注意每个服务都必须通过 image 指令指定镜像或 build 指令(需要 Dockerfile)等来自动构建生成镜像。如果使用 build 指令,在 Dockerfile 中设置的选项(例如:CMD, EXPOSE, VOLUME, ENV 等) 将会自动被获取,无需在 docker-compose.yml 中重复设置。下面分别介绍各个指令的用法。build指定 Dockerfile 所在文件夹的路径(可以是绝对路径,或者相对 docker-compose.yml 文件的路径)。 Compose 将会利用它自动构建这个镜像,然后使用这个镜像。version: '3' services: webapp: build: ./dir你也可以使用 context 指令指定 Dockerfile 所在文件夹的路径。使用 dockerfile 指令指定 Dockerfile 文件名。使用 arg 指令指定构建镜像时的变量。version: '3' services: webapp: build: context: ./dir dockerfile: Dockerfile-alternate args: buildno: 1使用 cache_from 指定构建镜像的缓存build: context: . cache_from: - alpine:latest - corp/web_app:3.14cap_add, cap_drop指定容器的内核能力(capacity)分配。例如,让容器拥有所有能力可以指定为:cap_add: - ALL去掉 NET_ADMIN 能力可以指定为:cap_drop: - NET_ADMINcommand覆盖容器启动后默认执行的命令。command: echo "hello world"configs仅用于 Swarm mode,详细内容请查看 Swarm mode 一节。cgroup_parent指定父 cgroup 组,意味着将继承该组的资源限制。例如,创建了一个 cgroup 组名称为 cgroups_1。cgroup_parent: cgroups_1container_name指定容器名称。默认将会使用 项目名称_服务名称_序号 这样的格式。container_name: docker-web-container注意: 指定容器名称后,该服务将无法进行扩展(scale),因为 Docker 不允许多个容器具有相同的名称。deploy仅用于 Swarm mode,详细内容请查看 Swarm mode 一节devices指定设备映射关系。devices: - "/dev/ttyUSB1:/dev/ttyUSB0"depends_on解决容器的依赖、启动先后的问题。以下例子中会先启动 redis db 再启动 webversion: '3' services: web: build: . depends_on: - db - redis redis: image: redis db: image: postgres注意:web 服务不会等待 redis db 「完全启动」之后才启动。dns自定义 DNS 服务器。可以是一个值,也可以是一个列表。dns: 8.8.8.8 dns: - 8.8.8.8 - 114.114.114.114dns_search配置 DNS 搜索域。可以是一个值,也可以是一个列表。dns_search: example.com dns_search: - domain1.example.com - domain2.example.comtmpfs挂载一个 tmpfs 文件系统到容器。tmpfs: /run tmpfs: - /run - /tmpenv_file从文件中获取环境变量,可以为单独的文件路径或列表。如果通过 docker-compose -f FILE 方式来指定 Compose 模板文件,则 env_file 中变量的路径会基于模板文件路径。如果有变量名称与 environment 指令冲突,则按照惯例,以后者为准。env_file: .env env_file: - ./common.env - ./apps/web.env - /opt/secrets.env环境变量文件中每一行必须符合格式,支持 # 开头的注释行。# common.env: Set development environment PROG_ENV=developmentenvironment设置环境变量。你可以使用数组或字典两种格式。只给定名称的变量会自动获取运行 Compose 主机上对应变量的值,可以用来防止泄露不必要的数据。environment: RACK_ENV: development SESSION_SECRET: environment: - RACK_ENV=development - SESSION_SECRET如果变量名称或者值中用到 true|false,yes|no 等表达 布尔 含义的词汇,最好放到引号里,避免 YAML 自动解析某些内容为对应的布尔语义。这些特定词汇,包括y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFFexpose暴露端口,但不映射到宿主机,只被连接的服务访问。仅可以指定内部端口为参数expose: - "3000" - "8000"external_links注意:不建议使用该指令。链接到 docker-compose.yml 外部的容器,甚至并非 Compose 管理的外部容器。external_links: - redis_1 - project_db_1:mysql - project_db_1:postgresqlextra_hosts类似 Docker 中的 --add-host 参数,指定额外的 host 名称映射信息。extra_hosts: - "googledns:8.8.8.8" - "dockerhub:52.1.157.61"会在启动后的服务容器中 /etc/hosts 文件中添加如下两条条目。8.8.8.8 googledns 52.1.157.61 dockerhubhealthcheck通过命令检查容器是否健康运行。healthcheck: test: ["CMD", "curl", "-f", "http://localhost"] interval: 1m30s timeout: 10s retries: 3image指定为镜像名称或镜像 ID。如果镜像在本地不存在,Compose 将会尝试拉取这个镜像。image: ubuntu image: orchardup/postgresql image: a4bc65fdlabels为容器添加 Docker 元数据(metadata)信息。例如可以为容器添加辅助说明信息。labels: com.startupteam.description: "webapp for a startup team" com.startupteam.department: "devops department" com.startupteam.release: "rc3 for v1.0"links注意:不推荐使用该指令。logging配置日志选项。logging: driver: syslog options: syslog-address: "tcp://192.168.0.42:123"目前支持三种日志驱动类型。driver: "json-file" driver: "syslog" driver: "none"options 配置日志驱动的相关参数。options: max-size: "200k" max-file: "10"network_mode设置网络模式。使用和 docker run 的 --network 参数一样的值。network_mode: "bridge" network_mode: "host" network_mode: "none" network_mode: "service:[service name]" network_mode: "container:[container name/id]"networks配置容器连接的网络。version: "3" services: some-service: networks: - some-network - other-network networks: some-network: other-network:pid跟主机系统共享进程命名空间。打开该选项的容器之间,以及容器和宿主机系统之间可以通过进程 ID 来相互访问和操作。pid: "host"ports暴露端口信息。使用宿主端口:容器端口 (HOST:CONTAINER) 格式,或者仅仅指定容器的端口(宿主将会随机选择端口)都可以。ports: - "3000" - "8000:8000" - "49100:22" - "127.0.0.1:8001:8001"注意:当使用 HOST:CONTAINER 格式来映射端口时,如果你使用的容器端口小于 60 并且没放到引号里,可能会得到错误结果,因为 YAML 会自动解析 xx:yy 这种数字格式为 60 进制。为避免出现这种问题,建议数字串都采用引号包括起来的字符串格式。secrets存储敏感数据,例如 mysql 服务密码。version: "3.1" services: mysql: image: mysql environment: MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_password secrets: - db_root_password - my_other_secret secrets: my_secret: file: ./my_secret.txt my_other_secret: external: truesecurity_opt指定容器模板标签(label)机制的默认属性(用户、角色、类型、级别等)。例如配置标签的用户名和角色名。security_opt: - label:user:USER - label:role:ROLEstop_signal设置另一个信号来停止容器。在默认情况下使用的是 SIGTERM 停止容器。stop_signal: SIGUSR1sysctls配置容器内核参数。sysctls: net.core.somaxconn: 1024 net.ipv4.tcp_syncookies: 0 sysctls: - net.core.somaxconn=1024 - net.ipv4.tcp_syncookies=0ulimits指定容器的 ulimits 限制值。例如,指定最大进程数为 65535,指定文件句柄数为 20000(软限制,应用可以随时修改,不能超过硬限制) 和 40000(系统硬限制,只能 root 用户提高)。 ulimits: nproc: 65535 nofile: soft: 20000 hard: 40000volumes数据卷所挂载路径设置。可以设置为宿主机路径(HOST:CONTAINER)或者数据卷名称(VOLUME:CONTAINER),并且可以设置访问模式 (HOST:CONTAINER:ro)。该指令中路径支持相对路径。volumes: - /var/lib/mysql - cache/:/tmp/cache - ~/configs:/etc/configs/:ro如果路径为数据卷名称,必须在文件中配置数据卷。version: "3" services: my_src: image: mysql:8.0 volumes: - mysql_data:/var/lib/mysql volumes: mysql_data:其它指令此外,还有包括 domainname, entrypoint, hostname, ipc, mac_address, privileged, read_only, shm_size, restart, stdin_open, tty, user, working_dir 等指令,基本跟 docker run 中对应参数的功能一致。指定服务容器启动后执行的入口文件。entrypoint: /code/entrypoint.sh指定容器中运行应用的用户名。user: nginx指定容器中工作目录。working_dir: /code指定容器中搜索域名、主机名、mac 地址等。domainname: your_website.com hostname: test mac_address: 08-00-27-00-0C-0A允许容器中运行一些特权命令。privileged: true指定容器退出后的重启策略为始终重启。该命令对保持服务始终运行十分有效,在生产环境中推荐配置为 always 或者 unless-stopped。restart: always以只读模式挂载容器的 root 文件系统,意味着不能对容器内容进行修改。read_only: true打开标准输入,可以接受外部输入。stdin_open: true模拟一个伪终端。tty: true读取变量Compose 模板文件支持动态读取主机的系统环境变量和当前目录下的 .env 文件中的变量。例如,下面的 Compose 文件将从运行它的环境中读取变量 ${MONGO_VERSION} 的值,并写入执行的指令中。 ··· version: "3" services: db: image: "mongo:${MONGO_VERSION}" ··· 如果执行 MONGO_VERSION=3.2 docker-compose up 则会启动一个 mongo:3.2 镜像的容器;如果执行 MONGO_VERSION=2.8 docker-compose up 则会启动一个 mongo:2.8 镜像的容器。若当前目录存在 .env 文件,执行 docker-compose 命令时将从该文件中读取变量。在当前目录新建 .env 文件并写入以下内容。# 支持 # 号注释 MONGO_VERSION=3.6执行 docker-compose up 则会启动一个 mongo:3.6 镜像的容器。实战 WordPress本小节内容适合 PHP 开发人员阅读。Compose 可以很便捷的让 Wordpress 运行在一个独立的环境中。创建空文件夹假设新建一个名为 wordpress 的文件夹,然后进入这个文件夹。创建 docker-compose.yml 文件docker-compose.yml 文件将开启一个 wordpress 服务和一个独立的 MySQL 实例:version: "3" services: db: image: mysql:8.0 command: - --default_authentication_plugin=mysql_native_password - --character-set-server=utf8mb4 - --collation-server=utf8mb4_unicode_ci volumes: - db_data:/var/lib/mysql restart: always environment: MYSQL_ROOT_PASSWORD: somewordpress MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: wordpress wordpress: depends_on: - db image: wordpress:latest ports: - "8000:80" restart: always environment: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: wordpress volumes: db_data:构建并运行项目运行 docker-compose up -d Compose 就会拉取镜像再创建我们所需要的镜像,然后启动 wordpress 和数据库容器。 接着浏览器访问 127.0.0.1:8000 端口就能看到 WordPress 安装界面了。
2021年02月10日
2 阅读
0 评论
0 点赞
2021-02-10
Docker系列教程-高级网络配置(八)
快速配置指南下面是一个跟 Docker 网络相关的命令列表。 其中有些命令选项只有在 Docker 服务启动的时候才能配置,而且不能马上生效。 -b BRIDGE 或 --bridge=BRIDGE 指定容器挂载的网桥 ---bip=CIDR 定制 docker0 的掩码 -H SOCKET... 或 --host=SOCKET... Docker 服务端接收命令的通道 ---icc=true|false 是否支持容器之间进行通信 ---ip-forward=true|false 请看下文容器之间的通信 ---iptables=true|false 是否允许 Docker 添加 iptables 规则 ---mtu=BYTES 容器网络中的 MTU 下面2个命令选项既可以在启动服务时指定,也可以在启动容器时指定。在 Docker 服务启动的时候指定则会成为默认值,后面执行 docker run 时可以覆盖设置的默认值。---dns=IP_ADDRESS... 使用指定的DNS服务器 ---dns-search=DOMAIN... 指定DNS搜索域最后这些选项只有在 docker run 执行时使用,因为它是针对容器的特性内容。 --h HOSTNAME 或 --hostname=HOSTNAME 配置容器主机名 ---link=CONTAINER_NAME:ALIAS 添加到另一个容器的连接 ---net=bridge|none|container:NAME_or_ID|host 配置容器的桥接模式 --p SPEC 或 --publish=SPEC 映射容器端口到宿主主机 --P or --publish-all=true|false 映射容器所有端口到宿主主机 容器访问控制容器的访问控制,主要通过 Linux 上的 iptables 防火墙来进行管理和实现。iptables 是 Linux 上默认的防火墙软件,在大部分发行版中都自带。容器访问外部网络容器要想访问外部网络,需要本地系统的转发支持。在Linux 系统中,检查转发是否打开。#sysctl net.ipv4.ip_forward net.ipv4.ip_forward = 1如果为 0,说明没有开启转发,则需要手动打开。$sysctl -w net.ipv4.ip_forward=1如果在启动 Docker 服务的时候设定 --ip-forward=true, Docker 就会自动设定系统的 ip_forward 参数为 1。容器之间访问容器之间相互访问,需要两方面的支持。容器的网络拓扑是否已经互联。默认情况下,所有容器都会被连接到 docker0 网桥上。本地系统的防火墙软件 -- iptables 是否允许通过。访问所有端口当启动 Docker 服务(即 dockerd)的时候,默认会添加一条转发策略到本地主机 iptables 的 FORWARD 链上。策略为通过(ACCEPT)还是禁止(DROP)取决于配置--icc=true(缺省值)还是 --icc=false。当然,如果手动指定 --iptables=false 则不会添加 iptables 规则。可见,默认情况下,不同容器之间是允许网络互通的。如果为了安全考虑,可以在 /etc/docker/daemon.json 文件中配置 {"icc": false} 来禁止它。访问指定端口在通过 -icc=false 关闭网络访问后,还可以通过 --link=CONTAINER_NAME:ALIAS 选项来访问容器的开放端口。例如,在启动 Docker 服务时,可以同时使用 icc=false --iptables=true 参数来关闭允许相互的网络访问,并让 Docker 可以修改系统中的 iptables 规则。此时,系统中的 iptables 规则可能是类似#iptables -nL ... Chain FORWARD (policy ACCEPT) target prot opt source destination DROP all -- 0.0.0.0/0 0.0.0.0/0 ...之后,启动容器(docker run)时使用 --link=CONTAINER_NAME:ALIAS 选项。Docker 会在 iptable 中为 两个容器分别添加一条 ACCEPT 规则,允许相互访问开放的端口(取决于 Dockerfile 中的 EXPOSE 指令)。当添加了 --link=CONTAINER_NAME:ALIAS 选项后,添加了 iptables 规则。# sudo iptables -nL ... Chain FORWARD (policy ACCEPT) target prot opt source destination ACCEPT tcp -- 172.17.0.2 172.17.0.3 tcp spt:80 ACCEPT tcp -- 172.17.0.3 172.17.0.2 tcp dpt:80 DROP all -- 0.0.0.0/0 0.0.0.0/0注意:--link=CONTAINER_NAME:ALIAS 中的 CONTAINER_NAME 目前必须是 Docker 分配的名字,或使用 --name 参数指定的名字。主机名则不会被识别。端口映射实现默认情况下,容器可以主动访问到外部网络的连接,但是外部网络无法访问到容器。容器访问外部实现容器所有到外部网络的连接,源地址都会被 NAT 成本地系统的 IP 地址。这是使用 iptables 的源地址伪装操作实现的。查看主机的 NAT 规则。# sudo iptables -t nat -nL ... Chain POSTROUTING (policy ACCEPT) target prot opt source destination MASQUERADE all -- 172.17.0.0/16 !172.17.0.0/16 ...其中,上述规则将所有源地址在 172.17.0.0/16 网段,目标地址为其他网段(外部网络)的流量动态伪装为从系统网卡发出。MASQUERADE 跟传统 SNAT 的好处是它能动态从网卡获取地址。外部访问容器实现容器允许外部访问,可以在 docker run 时候通过 -p 或 -P 参数来启用。不管用那种办法,其实也是在本地的 iptable 的 nat 表中添加相应的规则。使用 -P 时:# iptables -t nat -nL ... Chain DOCKER (2 references) target prot opt source destination DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:49153 to:172.17.0.2:80使用 -p 80:80 时:# iptables -t nat -nL Chain DOCKER (2 references) target prot opt source destination DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 to:172.17.0.2:80注意:这里的规则映射了 0.0.0.0,意味着将接受主机来自所有接口的流量。用户可以通过 -p IP:host_port:container_port 或 -p IP::port 来指定允许访问容器的主机上的 IP、接口等,以制定更严格的规则。如果希望永久绑定到某个固定的 IP 地址,可以在 Docker 配置文件 /etc/docker/daemon.json 中添加如下内容。{ "ip": "0.0.0.0" }配置 docker0 网桥Docker 服务默认会创建一个 docker0 网桥(其上有一个 docker0 内部接口),它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。Docker 默认指定了 docker0 接口 的 IP 地址和子网掩码,让主机和容器之间可以通过网桥相互通信,它还给出了 MTU(接口允许接收的最大传输单元),通常是 1500 Bytes,或宿主主机网络路由上支持的默认值。这些值都可以在服务启动的时候进行配置。--bip=CIDR IP 地址加掩码格式,例如 192.168.1.5/24--mtu=BYTES 覆盖默认的 Docker mtu 配置也可以在配置文件中配置 DOCKER_OPTS,然后重启服务。由于目前 Docker 网桥是 Linux 网桥,用户可以使用 brctl show 来查看网桥和端口连接信息。# sudo brctl show bridge name bridge id STP enabled interfaces docker0 8000.3a1d7362b4ee no veth65f9 vethdda6注:brctl 命令在 Debian、Ubuntu 中可以使用 sudo apt-get install bridge-utils 来安装。每次创建一个新容器的时候,Docker 从可用的地址段中选择一个空闲的 IP 地址分配给容器的 eth0 端口。使用本地主机上 docker0 接口的 IP 作为所有容器的默认网关。# sudo docker run -i -t --rm base /bin/bash # ip addr show eth0 24: eth0: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 32:6f:e0:35:57:91 brd ff:ff:ff:ff:ff:ff inet 172.17.0.3/16 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::306f:e0ff:fe35:5791/64 scope link valid_lft forever preferred_lft forever # ip route default via 172.17.42.1 dev eth0 172.17.0.0/16 dev eth0 proto kernel scope link src 172.17.0.3自定义网桥除了默认的 docker0 网桥,用户也可以指定网桥来连接各个容器。在启动 Docker 服务的时候,使用 -b BRIDGE或--bridge=BRIDGE 来指定使用的网桥。如果服务已经运行,那需要先停止服务,并删除旧的网桥。# systemctl stop docker # ip link set dev docker0 down # brctl delbr docker0然后创建一个网桥 bridge0。# brctl addbr bridge0 # ip addr add 192.168.5.1/24 dev bridge0 # ip link set dev bridge0 up查看确认网桥创建并启动。# ip addr show bridge0 4: bridge0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state UP group default link/ether 66:38:d0:0d:76:18 brd ff:ff:ff:ff:ff:ff inet 192.168.5.1/24 scope global bridge0 valid_lft forever preferred_lft forever在 Docker 配置文件 /etc/docker/daemon.json 中添加如下内容,即可将 Docker 默认桥接到创建的网桥上。{ "bridge": "bridge0", }启动 Docker 服务。新建一个容器,可以看到它已经桥接到了 bridge0 上。可以继续用 brctl show 命令查看桥接的信息。另外,在容器中可以使用 ip addr 和 ip route 命令来查看 IP 地址配置和路由信息。编辑网络配置文件Docker 1.2.0 开始支持在运行中的容器里编辑 /etc/hosts, /etc/hostname 和 /etc/resolv.conf 文件。但是这些修改是临时的,只在运行的容器中保留,容器终止或重启后并不会被保存下来,也不会被 docker commit 提交。实例:创建一个点到点连接默认情况下,Docker 会将所有容器连接到由 docker0 提供的虚拟子网中。用户有时候需要两个容器之间可以直连通信,而不用通过主机网桥进行桥接。解决办法很简单:创建一对 peer 接口,分别放到两个容器中,配置成点到点链路类型即可。首先启动 2 个容器:# docker run -i -t --rm --net=none base /bin/bash root@1f1f4c1f931a:/# # docker run -i -t --rm --net=none base /bin/bash root@12e343489d2f:/#找到进程号,然后创建网络命名空间的跟踪文件。# docker inspect -f '{{.State.Pid}}' 1f1f4c1f931a 2989 # docker inspect -f '{{.State.Pid}}' 12e343489d2f 3004 # mkdir -p /var/run/netns # ln -s /proc/2989/ns/net /var/run/netns/2989 # ln -s /proc/3004/ns/net /var/run/netns/3004创建一对 peer 接口,然后配置路由# sudo ip link add A type veth peer name B # sudo ip link set A netns 2989 # sudo ip netns exec 2989 ip addr add 10.1.1.1/32 dev A # sudo ip netns exec 2989 ip link set A up # sudo ip netns exec 2989 ip route add 10.1.1.2/32 dev A # sudo ip link set B netns 3004 # sudo ip netns exec 3004 ip addr add 10.1.1.2/32 dev B # sudo ip netns exec 3004 ip link set B up # sudo ip netns exec 3004 ip route add 10.1.1.1/32 dev B现在这 2 个容器就可以相互 ping 通,并成功建立连接。点到点链路不需要子网和子网掩码。此外,也可以不指定 --net=none 来创建点到点链路。这样容器还可以通过原先的网络来通信。利用类似的办法,可以创建一个只跟主机通信的容器。但是一般情况下,更推荐使用 --icc=false 来关闭容器之间的通信。
2021年02月10日
9 阅读
0 评论
0 点赞
2021-02-09
Docker系列教程-使用网络(八)
使用网络Docker 允许通过外部访问容器或容器互联的方式来提供网络服务。外部访问容器容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过 -P 或 -p 参数来指定端口映射。当使用 -P 标记时,Docker 会随机映射一个端口到内部容器开放的网络端口。使用 docker container ls 可以看到,本地主机的 32768 被映射到了容器的 80 端口。此时访问本机的 32768 端口即可访问容器内 NGINX 默认页面。#docker run -d -P nginx:alpine #docker container ls -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES fae320d08268 nginx:alpine "/docker-entrypoint.…" 24 seconds ago Up 20 seconds 0.0.0.0:32768->80/tcp bold_mcnulty同样的,可以通过 docker logs 命令来查看访问记录。#docker logs fa 172.17.0.1 - - [25/Aug/2020:08:34:04 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:80.0) Gecko/20100101 Firefox/80.0" "-"-p 则可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器。支持的格式有 ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort。映射所有接口地址使用 hostPort:containerPort 格式本地的 80 端口映射到容器的 80 端口,可以执行#docker run -d -p 80:80 nginx:alpine此时默认会绑定本地所有接口上的所有地址。映射到指定地址的指定端口可以使用 ip:hostPort:containerPort 格式指定映射使用一个特定地址,比如 localhost 地址 127.0.0.1#docker run -d -p 127.0.0.1:80:80 nginx:alpine映射到指定地址的任意端口使用 ip::containerPort 绑定 localhost 的任意端口到容器的 80 端口,本地主机会自动分配一个端口。#docker run -d -p 127.0.0.1::80 nginx:alpine还可以使用 udp 标记来指定 udp 端口#docker run -d -p 127.0.0.1:80:80/udp nginx:alpine查看映射端口配置使用 docker port 来查看当前映射的端口配置,也可以查看到绑定的地址#docker port fa 80 0.0.0.0:32768注意:容器有自己的内部网络和 ip 地址(使用 docker inspect 查看,Docker 还可以有一个可变的网络配置。)-p 标记可以多次使用来绑定多个端口例如#docker run -d \ -p 80:80 \ -p 443:443 \ nginx:alpine容器互联如果你之前有 Docker 使用经验,你可能已经习惯了使用 --link 参数来使容器互联。随着 Docker 网络的完善,强烈建议大家将容器加入自定义的 Docker 网络来连接多个容器,而不是使用 --link 参数。新建网络下面先创建一个新的 Docker 网络。#docker network create -d bridge my-net-d 参数指定 Docker 网络类型,有 bridge overlay。其中 overlay 网络类型用于 Swarm mode,在本小节中你可以忽略它。连接容器运行一个容器并连接到新建的 my-net 网络#docker run -it --rm --name busybox1 --network my-net busybox sh打开新的终端,再运行一个容器并加入到 my-net 网络#docker run -it --rm --name busybox2 --network my-net busybox sh再打开一个新的终端查看容器信息#docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b47060aca56b busybox "sh" 11 minutes ago Up 11 minutes busybox2 8720575823ec busybox "sh" 16 minutes ago Up 16 minutes busybox1下面通过 ping 来证明 busybox1 容器和 busybox2 容器建立了互联关系。在 busybox1 容器输入以下命令/ # ping busybox2 PING busybox2 (172.19.0.3): 56 data bytes 64 bytes from 172.19.0.3: seq=0 ttl=64 time=0.072 ms 64 bytes from 172.19.0.3: seq=1 ttl=64 time=0.118 ms用 ping 来测试连接 busybox2 容器,它会解析成 172.19.0.3。同理在 busybox2 容器执行 ping busybox1,也会成功连接到。/ # ping busybox1 PING busybox1 (172.19.0.2): 56 data bytes 64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.064 ms 64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.143 ms这样,busybox1 容器和 busybox2 容器建立了互联关系。Docker Compose如果你有多个容器之间需要互相连接,推荐使用 Docker Compose。配置 DNS如何自定义配置容器的主机名和 DNS 呢?秘诀就是 Docker 利用虚拟文件来挂载容器的 3 个相关配置文件。在容器中使用 mount 命令可以看到挂载信息:# mount /dev/disk/by-uuid/1fec...ebdf on /etc/hostname type ext4 ... /dev/disk/by-uuid/1fec...ebdf on /etc/hosts type ext4 ... tmpfs on /etc/resolv.conf type tmpfs ...这种机制可以让宿主主机 DNS 信息发生更新后,所有 Docker 容器的 DNS 配置通过 /etc/resolv.conf 文件立刻得到更新。配置全部容器的 DNS ,也可以在 /etc/docker/daemon.json 文件中增加以下内容来设置。{ "dns" : [ "114.114.114.114", "8.8.8.8" ] }这样每次启动的容器 DNS 自动配置为 114.114.114.114 和 8.8.8.8。使用以下命令来证明其已经生效。#docker run -it --rm ubuntu:18.04 cat etc/resolv.conf nameserver 114.114.114.114 nameserver 8.8.8.8如果用户想要手动指定容器的配置,可以在使用 docker run 命令启动容器时加入如下参数:-h HOSTNAME 或者 --hostname=HOSTNAME 设定容器的主机名,它会被写到容器内的 /etc/hostname 和 /etc/hosts。但它在容器外部看不到,既不会在 docker container ls 中显示,也不会在其他的容器的 /etc/hosts 看到。--dns=IP_ADDRESS 添加 DNS 服务器到容器的 /etc/resolv.conf 中,让容器用这个服务器来解析所有不在 /etc/hosts 中的主机名。--dns-search=DOMAIN 设定容器的搜索域,当设定搜索域为 .example.com 时,在搜索一个名为 host 的主机时,DNS 不仅搜索 host,还会搜索 host.example.com。注意:如果在容器启动时没有指定最后两个参数,Docker 会默认用主机上的 /etc/resolv.conf 来配置容器。
2021年02月09日
2 阅读
0 评论
0 点赞
2021-02-08
Docker系列教程-数据管理(七)
数据管理这一章介绍如何在 Docker 内部以及容器之间管理数据,在容器中管理数据主要有两种方式: 数据卷(Volumes) 挂载主机目录 (Bind mounts) 数据卷数据卷 是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性: 数据卷 可以在容器之间共享和重用 对 数据卷 的修改会立马生效 对 数据卷 的更新,不会影响镜像 数据卷 默认会一直存在,即使容器被删除 注意:数据卷 的使用,类似于 Linux 下对目录或文件进行 mount,镜像中的被指定为挂载点的目录中的文件会复制到数据卷中(仅数据卷为空时会复制)。创建一个数据卷#docker volume create my-vol查看所有的 数据卷#docker volume ls DRIVER VOLUME NAME local my-vol在主机里使用以下命令可以查看指定 数据卷 的信息#docker volume inspect my-vol [ { "Driver": "local", "Labels": {}, "Mountpoint": "/var/lib/docker/volumes/my-vol/_data", "Name": "my-vol", "Options": {}, "Scope": "local" } ]启动一个挂载数据卷的容器在用 docker run 命令的时候,使用 --mount 标记来将 数据卷 挂载到容器里。在一次 docker run 中可以挂载多个 数据卷。下面创建一个名为 web 的容器,并加载一个 数据卷 到容器的 /usr/share/nginx/html 目录。#docker run -d -P \ --name web \ # -v my-vol:/usr/share/nginx/html \ --mount source=my-vol,target=/usr/share/nginx/html \ nginx:alpine查看数据卷的具体信息在主机里使用以下命令可以查看 web 容器的信息#docker inspect web数据卷 信息在 "Mounts" Key 下面"Mounts": [ { "Type": "volume", "Name": "my-vol", "Source": "/var/lib/docker/volumes/my-vol/_data", "Destination": "/usr/share/nginx/html", "Driver": "local", "Mode": "", "RW": true, "Propagation": "" } ],删除数据卷$ docker volume rm my-vol数据卷 是被设计用来持久化数据的,它的生命周期独立于容器,Docker 不会在容器被删除后自动删除 数据卷,并且也不存在垃圾回收这样的机制来处理没有任何容器引用的 数据卷。如果需要在删除容器的同时移除数据卷。可以在删除容器的时候使用 docker rm -v 这个命令。无主的数据卷可能会占据很多空间,要清理请使用以下命令#docker volume prune挂载主机目录挂载一个主机目录作为数据卷 使用 --mount 标记可以指定挂载一个本地主机的目录到容器中去。#docker run -d -P \ --name web \ # -v /src/webapp:/usr/share/nginx/html \ --mount type=bind,source=/src/webapp,target=/usr/share/nginx/html \ nginx:alpine上面的命令加载主机的 /src/webapp 目录到容器的 /usr/share/nginx/html目录。这个功能在进行测试的时候十分方便,比如用户可以放置一些程序到本地目录中,来查看容器是否正常工作。本地目录的路径必须是绝对路径,以前使用 -v 参数时如果本地目录不存在 Docker 会自动为你创建一个文件夹,现在使用 --mount 参数时如果本地目录不存在,Docker 会报错。Docker 挂载主机目录的默认权限是 读写,用户也可以通过增加 readonly 指定为 只读。#docker run -d -P \ --name web \ # -v /src/webapp:/usr/share/nginx/html:ro \ --mount type=bind,source=/src/webapp,target=/usr/share/nginx/html,readonly \ nginx:alpine加了 readonly 之后,就挂载为 只读 了。如果你在容器内 /usr/share/nginx/html 目录新建文件,会显示如下错误/usr/share/nginx/html # touch new.txt touch: new.txt: Read-only file system查看数据卷的具体信息在主机里使用以下命令可以查看 web 容器的信息#docker inspect web挂载主机目录 的配置信息在 "Mounts" Key 下面"Mounts": [ { "Type": "bind", "Source": "/src/webapp", "Destination": "/usr/share/nginx/html", "Mode": "", "RW": true, "Propagation": "rprivate" } ],挂载一个本地主机文件作为数据卷--mount 标记也可以从主机挂载单个文件到容器中#docker run --rm -it \ # -v $HOME/.bash_history:/root/.bash_history \ --mount type=bind,source=$HOME/.bash_history,target=/root/.bash_history \ ubuntu:18.04 \ bash root@2affd44b4667:/# history 1 ls 2 diskutil list这样就可以记录在容器输入过的命令了。
2021年02月08日
2 阅读
0 评论
0 点赞
1
2
3