Docker版本变化说明:
docker compose是什么:
docker compose作用:
docker compose安装:
方法一:下载 并安装docker compose
[root@linux-node1 ~]# curl -L https://github.com/docker/compose/releases/download/1.15.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
[root@linux-node1 ~]# chmod +x /usr/local/bin/docker-compose
#或者
pip install docker-compose
方法二:直接解压安装
unzip docker-compose-linux-x86_64.zip # 解压后只有一个文件 docker-compose
chmod +x docker-compose
mv docker-compose /usr/bin/
YAML文件格式及编写注意事项:
YAML文件格式注意事项:
compose配置:
# 字段 描述
build # 指定Dockerfile文件名构建镜像上下文路径
dockerfile
context
image # 指定镜像
command # 执行命令,覆盖默认命令
container_name # 指定容器名称,由于容器名称是唯一的,如果指定自定义名称,则无法scale
deploy # 指定部署和运行服务相关配置,只能在Swarm模式使用
environment # 添加环境变量
networks # 加入网络,引用顶级networks下条目
ports # 暴露端口,与-p相同,但端口不能低于60
volumes # 挂载宿主机路径或命名卷,如果是命名卷在顶级volumes定义卷名称
restart # 重启策略,默认no,always|on-failure|unless-staopped
hostname # 容器主机名
常用命令:
# 字段 描述
build # 重新构建服务
ps # 列出容器
up # 创建和启动容器
exec # 在容器里执行命令
scale # 指定一个服务容器启动数量
top # 显示容器进程
logs # 查看容器输出
down # 删除容器、网络、数据卷和镜像
stop # 停止
start # 启动
restart # 重启服务
# 文章最后有详细介绍
参考官方:https://docs.docker.com/compose/compose-file/
项目地址:https://gitee.com/edushiyanlou/django-docker
一键部署LNMP文件结构
├── docker-compose.yml # compose 的yml文件用于描述要构建的容器
├── mysql
│ ├── conf
│ │ └── my.cnf # my.cnf : mysql主配置文件
│ └── data # data 数据目录,当构建的时候会将mysql数据持久化到宿主机上
├── nginx
│ ├── Dockerfile # 构建nginx容器的 Dockerfile 文件
│ ├── nginx-1.12.1.tar.gz
│ └── nginx.conf # nginx的主配置文件
├── php
│ ├── Dockerfile # 构建php容器的 Dockerfile 文件
│ ├── php-5.6.31.tar.gz
│ └── php.ini
└── wwwroot
└── index.php # 网站根目录
docker-compose.yml
version: '3'
services:
nginx:
hostname: nginx
build:
context: ./nginx
dockerfile: Dockerfile
ports:
- 81:80
networks:
- lnmp
volumes:
- ./wwwroot:/usr/local/nginx/html
php:
hostname: php
build:
context: ./php
dockerfile: Dockerfile
networks:
- lnmp
volumes:
- ./wwwroot:/usr/local/nginx/html
mysql:
hostname: mysql
image: mysql:5.6
ports:
- 3306:3306
networks:
- lnmp
volumes:
- ./mysql/conf:/etc/mysql/conf.d
- ./mysql/data:/var/lib/mysql
command: --character-set-server=utf8
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_DATABASE: wordpress
MYSQL_USER: user
MYSQL_PASSWORD: user123
networks:
lnmp:
mysql/conf/my.conf
[mysqld]
user=mysql
port=3306
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
pid-file=/var/run/mysql/mysql.pid
log_error=/var/log/mysql/error.log
character_set_server = utf8
max_connections=3600
nginx/Dockerfile
FROM centos:7
MAINTAINER www.aliangedu.com
RUN yum install -y gcc gcc-c++ make openssl-devel pcre-devel
ADD nginx-1.12.1.tar.gz /tmp
RUN cd /tmp/nginx-1.12.1 && \
./configure --prefix=/usr/local/nginx && \
make -j 2 && \
make install
RUN rm -rf /tmp/nginx-1.12.1* && yum clean all
COPY nginx.conf /usr/local/nginx/conf
WORKDIR /usr/local/nginx
EXPOSE 80
CMD ["./sbin/nginx", "-g", "daemon off;"]
nginx/nginx.conf
FROM centos:7
MAINTAINER www.aliangedu.com
RUN yum install -y gcc gcc-c++ make openssl-devel pcre-devel
ADD nginx-1.12.1.tar.gz /tmp
RUN cd /tmp/nginx-1.12.1 && \
./configure --prefix=/usr/local/nginx && \
make -j 2 && \
make install
RUN rm -rf /tmp/nginx-1.12.1* && yum clean all
COPY nginx.conf /usr/local/nginx/conf
WORKDIR /usr/local/nginx
EXPOSE 80
CMD ["./sbin/nginx", "-g", "daemon off;"]
[root@linux-node2 compose_lnmp]# cat nginx/nginx.conf
user root;
worker_processes auto;
error_log logs/error.log info;
pid logs/nginx.pid;
events {
use epoll;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log logs/access.log main;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
root html;
index index.html index.php;
location ~ \.php$ {
root html;
fastcgi_pass php:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
}
php/Dockerfile
FROM centos:7
MAINTAINER www.aliangedu.com
RUN yum install -y gcc gcc-c++ make gd-devel libxml2-devel libcurl-devel libjpeg-devel libpng-devel openssl-devel
ADD php-5.6.31.tar.gz /tmp/
RUN cd /tmp/php-5.6.31 && \
./configure --prefix=/usr/local/php \
--with-config-file-path=/usr/local/php/etc \
--with-mysql --with-mysqli \
--with-openssl --with-zlib --with-curl --with-gd \
--with-jpeg-dir --with-png-dir --with-iconv \
--enable-fpm --enable-zip --enable-mbstring && \
make -j 4 && \
make install && \
cp /usr/local/php/etc/php-fpm.conf.default /usr/local/php/etc/php-fpm.conf && \
sed -i "s/127.0.0.1/0.0.0.0/" /usr/local/php/etc/php-fpm.conf && \
sed -i "21a \daemonize = no" /usr/local/php/etc/php-fpm.conf
COPY php.ini /usr/local/php/etc
RUN rm -rf /tmp/php-5.6.31* && yum clean all
WORKDIR /usr/local/php
EXPOSE 9000
CMD ["./sbin/php-fpm", "-c", "/usr/local/php/etc/php-fpm.conf"]
wwwroot/index.php
<?php phpinfo();?>
执行一键部署命令:
docker-compose -f docker-compose.yml up
docker-compose -f docker-compose.yml up -d # -d参数让程序运行在后台
说明:
http://192.168.0.211:81/ # 运行上面命令即可在页面打开php页面
注:如果想要使用其他页面直接将 wwwroot中的index.php问价进行替换即可
对docker-compose.yml说明
version: '3' # cocker compose版本号
services: # 顶级配置文件
nginx: # 服务名,可以通过服务名对容器进行管理
hostname: nginx # docker容器主机名
build: # 构建nginx 容器
context: ./nginx # 指定环境在当前目录的 nginx文件夹中
dockerfile: Dockerfile # 指定使用nginx文件夹中的Dockerfile进行构建
ports: # 暴露端口
- 81:80 # 将宿主机的81端口映射到容器的80端口
networks: # 容器使用的网络
- lnmp
volumes: # 指定容器数据卷挂载在宿主机路径
- ./wwwroot:/usr/local/nginx/html
php:
hostname: php
build:
context: ./php
dockerfile: Dockerfile
networks:
- lnmp
volumes:
- ./wwwroot:/usr/local/nginx/html
mysql:
hostname: mysql
image: mysql:5.6 # 直接引用mysql官方镜像仓库
ports:
- 3306:3306
networks:
- lnmp
volumes:
- ./mysql/conf:/etc/mysql/conf.d
- ./mysql/data:/var/lib/mysql
command: --character-set-server=utf8 # 接收mysql的命令,比如这里设置mysql的字符集
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_DATABASE: wordpress
MYSQL_USER: user
MYSQL_PASSWORD: user123
networks:
lnmp: # 创建一个网络
Docker-Compose
Docker Swarm
Kubernetes
核心作用:快速迭代、服务自愈
docker-compose部署django+nginx+uwsgi+celery+redis+mysql
项目图解
项目地址:https://gitee.com/edushiyanlou/django-docker
django-docker ## 项目根路径
│ .gitignore # git忽略不上传的文件
│ docker-compose.yml # docker-compose文件
│ Dockerfile # 部署django项目的dockerfile
│ README.md # 项目Readme说明
│ requirements.txt # 项目必须要安装的文件
│
├─nginx ## nginx容器配置文件
│ │ nginx.conf # /etc/nginx/nginx.conf配置文件
│ │
│ └─conf # /etc/nginx/conf.d配置nginx文件夹
│ default.conf
│
└─web ## 部署django项目的web容器
│ manage.py
│ uwsgi.ini # django项目的uwsgi配置文件
│
├─demoapp
│ │ admin.py
│ │ apps.py
│ │ models.py
│ │ tasks.py # 配置celery任务文件
│ │ tests.py
│ │ urls.py
│ │ views.py
│ │ __init__.py
│ │
│ ├─migrations
│ │ __init__.py # 引入celery
│ │
│ └─templates
│ └─demoapp
│ celery_detail.html # 查看具体celery执行结果页面
│ celery_index.html # 查看对应celery任务页面
│ index.html # 项目主页面
│
└─web
celery.py # celery配置文件
settings.py
urls.py
wsgi.py
__init__.py
初始化一个django项目
urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('', include('demoapp.urls')),
path('admin/', admin.site.urls),
]
demoapp/urls.py
from django.urls import path
from . import views
app_name = 'demoapp'
urlpatterns = [
path('', views.index, name='index'),
path('celery/', views.celery_index, name='celery_index'),
path('celery/random_add/', views.random_add, name='celery_random_add'),
path('celery/random_mul/', views.random_mul, name='celery_random_mul'),
path('celery/random_xsum/', views.random_xsum, name='celery_random_xsum'),
]
demoapp/views.py
import random
from django.shortcuts import render
from . import tasks
def index(request):
context = {}
return render(request, 'demoapp/index.html', context)
def celery_index(request):
context = {}
return render(request, 'demoapp/celery_index.html', context)
def random_add(request):
a, b = random.choices(range(100), k=2)
tasks.add.delay(a, b)
context = {'function_detail': 'add({}, {})'.format(a, b)}
return render(request, 'demoapp/celery_detail.html', context)
def random_mul(request):
a, b = random.choices(range(100), k=2)
tasks.mul.delay(a, b)
context = {'function_detail': 'mul({}, {})'.format(a, b)}
return render(request, 'demoapp/celery_detail.html', context)
def random_xsum(request):
array = random.choices(range(100), k=random.randint(1, 10))
tasks.xsum.delay(array)
context = {'function_detail': 'xsum({})'.format(array)}
return render(request, 'demoapp/celery_detail.html', context)
web/__init__.py
# This will make sure the app is always imported when
# Django starts so that shared_task will use this app.
from .celery import app as celery_app
__all__ = ['celery_app']
web/celery.py
import os
from celery import Celery
# 只要是想在自己的脚本中访问Django的数据库等文件就必须配置Django的环境变量
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'web.settings')
# app名字
app = Celery('web')
# 配置celery
class Config:
BROKER_URL = 'redis://redis:6379' # redis://127.0.0.1:6379
CELERY_RESULT_BACKEND = 'redis://redis:6379'
app.config_from_object(Config)
# 到各个APP里自动发现tasks.py文件
app.autodiscover_tasks()
demoapp/tasks.py
# Create your tasks here
from celery import shared_task
@shared_task
def add(x, y):
return x + y
@shared_task
def mul(x, y):
return x * y
@shared_task
def xsum(numbers):
return sum(numbers)
nginx容器相关配置文件:
django-docker\nginx\nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
django-docker\nginx\conf\default.conf
server {
listen 80;
server_name localhost;
charset utf-8;
client_max_body_size 10M;
location /static/ {
alias /django_static/;
}
location / {
include uwsgi_params;
uwsgi_pass web:8000;
}
}
web向配置文件:
django-docker\Dockerfile
FROM python:3
ENV PYTHONUNBUFFERED=1
RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
# ADD . /code/
django-docker\web\uwsgi.ini
[uwsgi]
socket=:8000
chdir=/code/web
module=web.wsgi:application
pidfile=/tmp/web-master.pid
master=True
vacuum=True
processes=1
max-requests=5000
docker-compose.yml文件:
docker-compose.yml
version: '3'
services:
mysql:
image: mysql:5.7
volumes:
- ./mysql:/var/lib/mysql
expose:
- "3306"
restart: always
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=djangodocker
- MYSQL_USER=django
- MYSQL_PASSWORD=django
nginx:
image: nginx:alpine
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/conf:/etc/nginx/conf.d
- ./web/staticfiles:/django_static
ports:
- "80:80"
depends_on:
- web
redis:
image: redis:alpine
expose:
- "6379"
restart: always
web:
build: .
# command: python manage.py runserver 0:8000
# ports:
# - "8000:8000"
command: uwsgi --ini uwsgi.ini
working_dir: /code/web
volumes:
- .:/code
expose:
- "8000"
depends_on:
- mysql
- redis
celery:
build: .
command: celery -A web worker -l info
working_dir: /code/web
volumes:
- .:/code
depends_on:
- mysql
- redis
docker-compose.yml详解:
version: '3' # cocker compose版本号
services: # 顶级配置文件
mysql: # 服务名: 容器建通信、管理容器
image: mysql:5.7 # 引入官方mysql镜像
volumes:
- ./mysql:/var/lib/mysql # 把当前文件夹下的 ./mysql文件夹挂载到docker容器 /var/lib/mysql 路径下
expose:
- "3306" # 将当前容器的端口3306端口暴露给link到本容器的容器
restart: always # 宿主机重启自动拉起这个docker容器
environment:
- MYSQL_ROOT_PASSWORD=root # mysql服务器root密码root
- MYSQL_DATABASE=djangodocker # 创建数据库 djangodocker
- MYSQL_USER=django # 创建一个用户 django
- MYSQL_PASSWORD=django # 用户密码为django
nginx:
image: nginx:alpine
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/conf:/etc/nginx/conf.d
- ./web/staticfiles:/django_static
ports:
- "80:80" # 绑定容器的80端口到主机的80端口
depends_on:
- web # 必须先启动web容器然才能启动nginx容器
redis:
image: redis:alpine
expose:
- "6379"
restart: always
web:
build: .
# command: python manage.py runserver 0:8000
# ports:
# - "8000:8000"
command: uwsgi --ini uwsgi.ini # 启动uwsgi命令
working_dir: /code/web # 项目工作路径
volumes:
- .:/code # 将当前文件夹下所有文件挂载到容器的 /code 文件夹
expose:
- "8000"
depends_on: # 必须mysql和reids容器启动后才能启动web容器
- mysql
- redis
celery:
build: .
command: celery -A web worker -l info
working_dir: /code/web
volumes:
- .:/code
depends_on:
- mysql
- redis
相似指令比较
'''1. expose 与 ports 比较'''
# ports: 绑定容器的端口到主机的端口,这样就可以在外网访问docker容器的服务
# expose: 将当前容器的端口3暴露给link到本容器的容器,expose不会将端口暴露给主机
'''2. depends_on 与 links区别'''
# depends_on: 指定本容器启动依赖的容器必须先启动
# links: 保证容器如果ip变化也能访问(基本已经弃用,因为不使用link仍然可以通过容器名称访问)
build 可以指定包含构建上下文的路径:
version: '2'
services:
webapp:
build: ./dir
build
build 可以指定包含构建上下文的路径:
version: '2'
services:
webapp:
build: ./dir
或者,作为一个对象,该对象具有上下文路径和指定的Dockerfile文件以及args参数值:
version: '2'
services:
webapp:
build:
context: ./dir
dockerfile: Dockerfile-alternate
args:
buildno: 1
webapp服务将会通过./dir目录下的Dockerfile-alternate文件构建容器镜像。
如果你同时指定image和build,则compose会通过build指定的目录构建容器镜像,而构建的镜像名为image中指定的镜像名和标签。
build: ./dir
image: webapp:tag
这将由./dir构建的名为webapp和标记为tag的镜像。
context
dockerfile
args
首先,在Dockerfile中指定要使用的参数:
ARG buildno
ARG password
RUN echo "Build number: $buildno"
RUN script-requiring-password.sh "$password"
然后在args键下指定参数。 你可以传递映射或列表:
build:
context: .
args:
buildno: 1
password: secret
build:
context: .
args:
- buildno=1
- password=secret
注意:YAML布尔值(true,false,yes,no,on,off)必须用引号括起来,以便解析器将它们解释为字符串。
image
指定启动容器的镜像,可以是镜像仓库/标签或者镜像id(或者id的前一部分)
image: redis
image: ubuntu:14.04
image: tutum/influxdb
image: example-registry.com:4000/postgresql
image: a4bc65fd
如果镜像不存在,Compose将尝试从官方镜像仓库将其pull下来,如果你还指定了build,在这种情况下,它将使用指定的build选项构建它,并使用image指定的名字和标记对其进行标记。
container_name
指定一个自定义容器名称,而不是生成的默认名称。
container_name: my-web-container
由于Docker容器名称必须是唯一的,因此如果指定了自定义名称,则无法将服务扩展到多个容器。
volumes
卷挂载路径设置。可以设置宿主机路径 (HOST:CONTAINER) 或加上访问模式 (HOST:CONTAINER:ro),挂载数据卷的默认权限是读写(rw),可以通过ro指定为只读。
你可以在主机上挂载相对路径,该路径将相对于当前正在使用的Compose配置文件的目录进行扩展。 相对路径应始终以 . 或者 .. 开始。
volumes:
# 只需指定一个路径,让引擎创建一个卷
- /var/lib/mysql
# 指定绝对路径映射
- /opt/data:/var/lib/mysql
# 相对于当前compose文件的相对路径
- ./cache:/tmp/cache
# 用户家目录相对路径
- ~/configs:/etc/configs/:ro
# 命名卷
- datavolume:/var/lib/mysql
但是,如果要跨多个服务并重用挂载卷,请在顶级volumes关键字中命名挂在卷,但是并不强制,如下的示例亦有重用挂载卷的功能,但是不提倡。
version: "3"
services:
web1:
build: ./web/
volumes:
- ../code:/opt/web/code
web2:
build: ./web/
volumes:
- ../code:/opt/web/code
注意:通过顶级volumes定义一个挂载卷,并从每个服务的卷列表中引用它, 这会替换早期版本的Compose文件格式中volumes_from。
version: "3"
services:
db:
image: db
volumes:
- data-volume:/var/lib/db
backup:
image: backup-service
volumes:
- data-volume:/var/lib/backup/data
volumes:
data-volume:
command
覆盖容器启动后默认执行的命令。
command: bundle exec thin -p 3000
该命令也可以是一个类似于dockerfile的列表:
command: ["bundle", "exec", "thin", "-p", "3000"]
links
链接到另一个服务中的容器。 请指定服务名称和链接别名(SERVICE:ALIAS),或者仅指定服务名称。
web:
links:
- db
- db:database
- redis
external_links
external_links:
- redis_1
- project_db_1:mysql
- project_db_1:postgresql
expose
expose:
- "3000"
- "8000"
ports
简单的短格式:
ports:
- "3000"
- "3000-3005"
- "8000:8000"
- "9090-9091:8080-8081"
- "49100:22"
- "127.0.0.1:8001:8001"
- "127.0.0.1:5000-5010:5000-5010"
- "6060:6060/udp"
在v3.2中ports的长格式的语法允许配置不能用短格式表示的附加字段。
长格式:
ports:
- target: 80
published: 8080
protocol: tcp
mode: host
target:容器内的端口
published:物理主机的端口
protocol:端口协议(tcp或udp)
mode:host 和ingress 两总模式,host用于在每个节点上发布主机端口,ingress 用于被负载平衡的swarm模式端口。
restart
no是默认的重启策略,在任何情况下都不会重启容器。 指定为always时,容器总是重新启动。 如果退出代码指示出现故障错误,则on-failure将重新启动容器。
restart: "no"
restart: always
restart: on-failure
restart: unless-stopped
environment
environment:
RACK_ENV: development
SHOW: 'true'
SESSION_SECRET:
environment:
- RACK_ENV=development
- SHOW=true
- SESSION_SECRET
pid
将PID模式设置为主机PID模式。 这就打开了容器与主机操作系统之间的共享PID地址空间。 使用此标志启动的容器将能够访问和操作裸机的命名空间中的其他容器,反之亦然。即打开该选项的容器可以相互通过进程 ID 来访问和操作。
pid: "host"
dns
配置 DNS 服务器。可以是一个值,也可以是一个列表。
dns: 8.8.8.8
dns:
- 8.8.8.8
- 9.9.9.9