Docker安装redis Sentinel(高可用)

redis介绍

redis集群有两种,一种是redis sentinel(哨兵),高可用集群,同时只有一个master,各实例数据保持一致;一种是redis cluster,分布式集群,同时有多个master,数据分片部署在各个master上。 哨兵模式简单说就是在后台有一个监控,监控当前的主机并巡逻主机下面的从机,如果某一时刻主机挂掉了,那么他会通过一种投票的机制从从机之中选举一台作为新的主机,并且其余的从机将会连接到这个新的主机上面,完成故障转移,主从模式就是一个中心化的结构,通过哨兵完成去中心化;本次要搭建的是redis sentinel。

Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance), 该系统执行以下三个任务:

  • 监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
  • 提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
  • 自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。

目录结构

1
2
3
4
5
6
7
8
9
redis
|--master
|--slave1
|--slave2
|--Dockerfile
|--redis.conf
|--docker-compose.yml
|--sentinel.conf
|--start.sh

制作镜像

整个集群可以分为一个master,N个slave,M个sentinel,本次以2个slave和3个sentinel为例

增加redis.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 使用守护进程模式
daemonize no
# 非保护模式,可以外网访问
protected-mode no
timeout 300
databases 16
rdbcompression yes
# 学习开发,使用最大日志级别,能够看到最多的日志信息
loglevel debug
port $redis_port
##授权密码,各个配置保持一致
##暂且禁用指令重命名
##rename-command
##开启AOF,禁用snapshot
appendonly yes
#slaveof redis-master $master_port
slave-read-only yes
maxclients 10000
maxmemory 1000mb

增加sentinel.conf

1
2
3
4
5
6
port $sentinel_port
dir "/tmp"
sentinel monitor mymaster redis-master $master_port 2
sentinel down-after-milliseconds mymaster 60000
sentinel failover-timeout manager1 180000
sentinel parallel-syncs manager1 2

这四行配置为一组,因为我们只有一个 master 节点,所以只配置了一个 master,可以配置多个 master,不用配置 slave 的信息,因为 slave 能够被自动检测到(master 节点会有关于 slave 的消息)

其他选项的基本格式如下:

sentinel <选项的名字> <主服务器的名字> <选项的值>

  • auth-pass:选项指定了 master 的连接密码。
  • down-after-milliseconds:选项指定了 Sentinel 认为服务器已经断线所需的毫秒数。
  • failover-timeout:如果在该时间(ms)内未能完成 failover 操作,则认为该 failover 失败。
  • parallel-syncs:选项指定了在执行故障转移时,最多可以有多少个从服务器同时对新的主服务器进行同步,这个数字越小,完成故障转移所需的时间就越长。

添加start.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
cd /conf
redis_role=$1
echo $redis_role
if [ $redis_role = "master" ] ; then
echo "master"
sed -i "s/\$redis_port/$redis_port/g" redis.conf
redis-server /conf/redis.conf
elif [ $redis_role = "slave" ] ; then
echo "slave"
sed -i "s/\$redis_port/$redis_port/g" redis.conf
sed -i "s/#slaveof/slaveof/g" redis.conf
sed -i "s/\$master_port/$master_port/g" redis.conf
redis-server /conf/redis.conf
elif [ $redis_role = "sentinel" ] ; then
echo "sentinel"
sed -i "s/\$sentinel_port/$sentinel_port/g" sentinel.conf
sed -i "s/\$master_port/$master_port/g" sentinel.conf
redis-sentinel /conf/sentinel.conf
else
echo "unknow role!"
fi #ifend

添加Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
FROM redis:4-alpine

# 设置时区
RUN apk add --update tzdata
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone


COPY redis.conf /conf/redis.conf
COPY sentinel.conf /conf/sentinel.conf
COPY start.sh /conf/start.sh
RUN chmod +x /conf/start.sh && chown redis:redis /conf/*
ENTRYPOINT ["sh","/conf/start.sh"]
CMD ["master"]

build镜像

在当前目录执行以下命令,创建redis:v1镜像。

1
docker build -t redis:v1 .

启动redis服务

在根目录创建master,slave1,slave2目录。

创建docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
version: '3'

services:
redis-master:
container_name: redis-master
build:
context: ./master
volumes:
- /master/data:/data
environment:
redis_port: '16379'
image: redis:v1
expose:
- "16379"
redis-slave1:
container_name: redis-slave1
build:
context:./slave1
volumes:
- /slave1/data:/data
environment:
master_port: '16379'
redis_port: '16380'
expose:
- "16380"
command:
- slave
image: redis:v1
redis-slave2:
container_name: redis-slave2
build:
context:./slave2
volumes:
- /slave2/data:/data
environment:
master_port: '16379'
redis_port: '16380'
expose:
- "16380"
command:
- slave
image: redis:v1
redis-sentinel-1:
container_name: redis-sentinel-1
environment:
master_port: '16379'
sentinel_port: '16381'
expose:
- "16381"
command:
- sentinel
depends_on:
- "redis-master"
- "redis-slave1"
- "redis-slave2"
image: redis:v1
redis-sentinel-2:
container_name: redis-sentinel-2
environment:
master_port: '16379'
sentinel_port: '16381'
expose:
- "16381"
command:
- sentinel
depends_on:
- "redis-master"
- "redis-slave1"
- "redis-slave2"
image: redis:v1
redis-sentinel-3:
container_name: redis-sentinel-3
environment:
master_port: '16379'
sentinel_port: '16381'
expose:
- "16381"
command:
- sentinel
depends_on:
- "redis-master"
- "redis-slave1"
- "redis-slave2"
image: redis:v1

运行以下命令以启动:

1
docker-compose up

可以选择添加-d参数以守护进程启动。

Redis Sentinel 故障转移测试

查看redis-master服务IP

1
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' redis-master

结果:

1
2
[root@localhost redis]# docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' redis-master
172.18.0.2

查看mymaster节点IP

1
docker exec redis-sentinel-1 redis-cli -p 16381 SENTINEL get-master-addr-by-name mymaster

结果:

1
2
3
[root@localhost redis]# docker exec redis-sentinel-1 redis-cli -p 16381 SENTINEL get-master-addr-by-name mymaster
172.18.0.2
16379

连接client

1
docker exec -it redis-master redis-cli -h 172.18.0.2 -p 16379

停止master节点

1
docker pause redis-master

查询master主节点IP

注意:中间有时间间隔。

1
docker exec redis-sentinel-1 redis-cli -p 16381 SENTINEL get-master-addr-by-name mymaster

结果:

1
2
3
[root@localhost redis]# docker exec redis-sentinel-1 redis-cli -p 16381 SENTINEL get-master-addr-by-name mymaster
172.18.0.4
16380

恢复redis-master服务

1
docker unpause redis-master

分别查看slave1,slave2服务IP

1
2
3
4
[root@localhost redis]# docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' redis-slave1
172.18.0.4
[root@localhost redis]# docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' redis-slave2
172.18.0.3

停止主节点

1
docker pause redis-slave1

查询主节点

1
docker exec redis-sentinel-1 redis-cli -p 16381 SENTINEL get-master-addr-by-name mymaster

结果:

1
2
3
localhost redis]# docker exec redis-sentinel-1 redis-cli -p 16381 SENTINEL get-master-addr-by-name mymaster
172.18.0.2
16379

至此,故障转移测试完成。

参考:

高可用Redis服务架构分析与搭建

Redis Sentinel 高可用服务架构搭建

Redis哨兵-实现Redis高可用

Redis Sentinel机制与用法(一)

Redis设置认证密码 Redis使用认证密码登录 在Redis集群中使用认证密码

Docker化高可用redis集群

Docker环境搭建redis集群(主从模式)

https://github.com/AliyunContainerService/redis-cluster/blob/master/test.sh

Redis 的 Sentinel 文档

Docker Compose简介

文档:https://docs.docker.com/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 来进行编排管理。

Docker Compose安装

https://docs.docker.com/compose/install/#install-compose

1
2
3
4
sudo curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version
docker-compose version 1.21.2, build a133471

常用命令

YAML配置命令

配置 说明
build 指定 Dockerfile 所在的目录地址,用于构建镜像,并使用此镜像创建容器,比如上面配置的 build: .
command 容器的执行命令
dns 自定义 dns 服务器
expose 暴露端口配置,但不映射到宿主机,只被连接的服务访问
extends docker-compose.yml的扩展,配置在服务中
image 使用的镜像名称或镜像 ID
links 链接到其它服务中的容器(一般桥接网络模式使用)
net 设置容器的网络模式(四种:bridge, none, container:[name or id]host
ports 暴露端口信息,主机和容器的端口映射
volumes 数据卷所挂载路径设置

Docker Compose 常用命令

命令 说明
docker-compose build 构建项目中的镜像,–force-rm:删除构建过程中的临时容器;–no-cache:不使用缓存构建;–pull:获取最新版本的镜像
docker-compose up -d 构建镜像、创建服务和启动项目,-d表示后台运行
docker-compose run ubuntu ls -d 指定服务上运行一个命令,-d表示后台运行
docker-compose logs 查看服务容器输出日志
docker-compose ps 列出项目中所有的容器
docker-compose pause [service_name] 暂停一个服务容器
docker-compose unpause [service_name] 恢复已暂停的一个服务容器
docker-compose restart 重启项目中的所有服务容器(也可以指定具体的服务)
docker-compose stop 停止运行项目中的所有服务容器(也可以指定具体的服务)
docker-compose start 启动已经停止项目中的所有服务容器(也可以指定具体的服务)
docker-compose rm 删除项目中的所有服务容器(也可以指定具体的服务),-f:强制删除(包含运行的)
docker-compose kill 强制停止项目中的所有服务容器(也可以指定具体的服务)

编写一个docker-compose.yml

dockers-compose.yml文件要定义在我们项目的文件夹下。

整体目录结构:

1
2
3
4
5
6
|-- docker.web
|--Dockerfile
|-- nginx
|--nginx.conf
|--Dockerfile
|--docker-compose.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
version: '3'

services:
dockerwebapp:
container_name:dockerwebapp
build:
context: ./docker.web
dockerfile: Dockerfile
expose:
- "5000"
ports:
- "5000:5000"
reverse-proxy:
container_name: reverse-proxy-nginx
build:
context: ./nginx
volumes:
- /etc/letsencrypt:/etc/letsencrypt/
ports:
- "80:80"
- "443:443"

docker.web下Dockerfile:

1
2
3
4
5
6
7
FROM microsoft/dotnet:latest
WORKDIR /app
COPY . /app
RUN dotnet restore
EXPOSE 5000
ENV ASPNETCORE_URLS http://*:5000
ENTRYPOINT ["dotnet","run"]

nginx下Dockerfile:

1
2
FROM nginx
COPY nginx.conf /etc/nginx/nginx.conf

nginx下nginx.conf配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
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;

server {
listen 80;
server_name www.shiyx.top;
return 301 https://www.shiyx.top$request_uri;
server_tokens off;
}
upstream app_servers {
server dockerwebapp:5000;
}
server {
listen 443 ssl http2;
ssl on;
server_name www.shiyx.top;
#$host该变量的值等于请求头中Host的值。如果Host无效时,那么就是处理该请求的server的名称。
#permanent: 永久性重定向。请求日志中的状态码为301
#nginx 对文档检测比较严格,所以if ( $host != 'www.csdn.com' ) 这些代码之间需要有空格隔开,不然会
#报错:unknown directive “if($host!=”
if ($host != 'www.shiyx.top' ){
rewrite ^/(.*)$ https://www.shiyx.top/$1 permanent;
}
ssl_certificate /etc/letsencrypt/live/shiyx.top/fullchain.pem;

ssl_certificate_key /etc/letsencrypt/live/shiyx.top/privkey.pem;

#禁止在header中出现服务器版本,防止黑客利用版本漏洞攻击
server_tokens off;
# 设置ssl/tls会话缓存的类型和大小。如果设置了这个参数一般是shared,buildin可能会参数内存碎片,默认是none,
#和off差不多,停用缓存。如shared:SSL:10m表示我>所有的nginx工作进程共享ssl会话缓存,
#网介绍说1M可以存放约4000个sessions。
ssl_session_cache shared:SSL:1m;

# 客户端可以重用会话缓存中ssl参数的过期时间,内网系统默认5分钟太短了,可以设成30m即30分钟甚至4h。
ssl_session_timeout 5m;

ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;

# 选择加密套件,不同的浏览器所支持的套件(和顺序)可能会不同。
# 这里指定的是OpenSSL库能够识别的写法,你可以通过 openssl -v cipher 'RC4:HIGH:!aNULL:!MD5'
#(后面是你所指定的套件加密算法) 来看所支持算法。
ssl_ciphers HIGH:!aNULL:!MD5;

# 设置协商加密算法时,优先使用我们服务端的加密套件,而不是客户端浏览器的加密套件。
ssl_prefer_server_ciphers on;

# 查看代理程序的ip
# sudo docker inspect --format '{{ .NetworkSettings.IPAddress }}' <container-ID>
location / {
proxy_pass http://app_servers;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_cache_bypass $http_upgrade;
}
location ~ /.well-known{
allow all;
}
}
}

其中要注意反向代理的配置:server dockerwebapp:5000;,其中ip部分直接指定的是docker-compose.yml中定义的第一个服务的名称dockerwebapp

启动compose

1
docker-compose up -d --build

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
ubuntu@ip-172-31-16-20:~/dotnet$ docker-compose up -d --build
Creating network "dotnet_default" with the default driver
Building dockerwebapp
Step 1/7 : FROM microsoft/dotnet:latest
---> 2ac9a416f201
Step 2/7 : WORKDIR /app
---> Using cache
---> 9449738bc5a1
Step 3/7 : COPY . /app
---> 63468e7420e1
Step 4/7 : RUN dotnet restore
---> Running in 24ecd554e076
Restore completed in 75.73 ms for /app/docker.web.csproj.
Restoring packages for /app/docker.web.csproj...
Restore completed in 464.93 ms for /app/docker.web.csproj.
Removing intermediate container 24ecd554e076
---> cdc5f195aa36
Step 5/7 : EXPOSE 5000
---> Running in af5717cc39b8
Removing intermediate container af5717cc39b8
---> afe466d24f6d
Step 6/7 : ENV ASPNETCORE_URLS http://*:5000
---> Running in d151cad8058d
Removing intermediate container d151cad8058d
---> d4e8dadfe89c
Step 7/7 : ENTRYPOINT ["dotnet","run"]
---> Running in de41a97d97a8
Removing intermediate container de41a97d97a8
---> 05c1f1c48653
Successfully built 05c1f1c48653
Successfully tagged dotnet_dockerwebapp:latest
Building reverse-proxy
Step 1/2 : FROM nginx
---> ae513a47849c
Step 2/2 : COPY nginx.conf /etc/nginx/nginx.conf
---> 458d9128600f
Successfully built 458d9128600f
Successfully tagged dotnet_reverse-proxy:latest
Creating reverse-proxy-nginx ... done
Creating dockerwebapp ... done

验证启动的服务:

1
sudo docker-compose ps

显示结果:

1
2
3
4
5
6
ubuntu@ip-172-31-16-20:~/dotnet$ docker-compose ps
Name Command State Ports
--------------------------------------------------------------------------------
dockerwebapp dotnet run Up 5000/tcp
reverse-proxy-nginx nginx -g daemon off; Up 0.0.0.0:443->443/tcp,
0.0.0.0:80->80/tcp

remove-orphans

1
docker-compose down --rmi local --remove-orphans

删除tag为none镜像

1
2
3
docker images -a|grep none|awk '{print $3}'|xargs docker rmi
## 显示依赖关系
docker image inspect --format='{{.RepoTags}} {{.Id}} {{.Parent}}' $(docker image ls -q --filter since=b64089162379)

其中b64089162379为镜像ID。

参考:

https://yeasy.gitbooks.io/docker_practice/content/compose/introduction.html

https://www.sep.com/sep-blog/2017/02/27/nginx-reverse-proxy-to-asp-net-core-separate-docker-containers/

https://www.cnblogs.com/sheng-jie/p/8116276.html

http://www.cnblogs.com/xishuai/p/docker-compose.html

http://www.cnblogs.com/lsxqw2004/p/6709766.html

获取docker容器(container)ip地址

使用命令方式

  • 命令
1
sudo docker inspect --format '{{ .NetworkSettings.IPAddress }}' <container-ID>
  • 命令2
1
2
3
sudo docker inspect <container id>

sudo docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <container_name_or_id>

进入容器内

命令:

1
2
sudo docker exec -it mynginx /bin/bash
cat /etc/hosts
1
2
3
4
5
6
7
8
9
ubuntu@ip-172-31-16-20:~/dotnet$ sudo docker exec -it mynginx /bin/bash
root@70e571d3bcab:/# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.4 70e571d3bcab

在 ~/.bashrc 中写一个 bash 函数

1
sudo vim ~/.bashrc

添加如下内容:

1
2
3
function docker_ip() {
sudo docker inspect --format '{{ .NetworkSettings.IPAddress }}' $1
}

然后执行:

1
source ~/.bashrc

最后调用函数:

1
docker_ip mynginx

所有容器名称及其IP地址

1
sudo docker inspect -f '{{.Name}} - {{.NetworkSettings.IPAddress }}' $(docker ps -aq)

如果使用docker-compose命令将是:

1
docker inspect -f '{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq)
1
sudo docker inspect --format='{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq)

可能遇到的问题:

1
2
3
4
5
6
7
8
ubuntu@ip-172-31-16-20:~/dotnet$ sudo docker inspect -f '{{.Name}} - {{.NetworkSettings.IPAddress }}' $(docker ps -aq)
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.37/containers/json?all=1: dial unix /var/run/docker.sock: connect: permission denied
"docker inspect" requires at least 1 argument.
See 'docker inspect --help'.

Usage: docker inspect [OPTIONS] NAME|ID [NAME|ID...] [flags]

Return low-level information on Docker objects

执行以下命令,将当前用户添加 docker 组:

1
2
3
sudo usermod -a -G docker $USER

sudo usermod -aG docker $USER

注销,重新登录:

1
logout

注意:注销并重新登录是必需的,因为除非您的会话关闭,否则组更改不会生效。

参考:
https://blog.csdn.net/sannerlittle/article/details/77063800

Nginx&Docker部署NetCore项目

Nginx运行在Docker

1
2
3
4
5
6
sudo docker container run \
-d \
-p 127.0.0.2:8080:80 \
--rm \
--name mynginx \
nginx

上面命令下载并运行官方的 Nginx image,默认是最新版本(latest)。如果本机安装过以前的版本,请删掉重新安装,因为只有 1.13.9 才开始支持 server push。

上面命令的各个参数含义如下:

1
2
3
4
-d:在后台运行
-p :容器的80端口映射到127.0.0.2:8080
--rm:容器停止运行后,自动删除容器文件
--name:容器的名字为mynginx

如果没有报错,就可以打开浏览器访问 127.0.0.2:8080 了。正常情况下,显示 Nginx 的欢迎页。

或者用curl显示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
ubuntu@ip-172-31-16-20:~/dotnet/conf$ curl http://127.0.0.1:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
ubuntu@ip-172-31-16-20:~/dotnet/conf$

然后,把这个容器终止,由于–rm参数的作用,容器文件会自动删除。

1
sudo docker container stop mynginx

拷贝配置

首先,把容器里面的 Nginx 配置文件拷贝到本地。

1
sudo docker container cp mynginx:/etc/nginx .

上面命令的含义是,把mynginx容器的/etc/nginx拷贝到当前目录。不要漏掉最后那个点。

执行完成后,当前目录应该多出一个nginx子目录。然后,把这个子目录改名为conf。

1
sudo mv nginx conf

容器终止:

1
sudo docker container stop mynginx

映射配置目录

1
2
3
4
5
6
7
sudo docker container run \
--name mynginx \
--rm \
--volume "$PWD/conf":/etc/nginx \
-p 80:80 \
-d \
nginx

–volume “$PWD/conf”:/etc/nginx表示把容器的配置目录/etc/nginx,映射到本地的conf子目录。

查看docker 容器日志:

1
sudo docker logs mynginx

映射证书

使用Let’s Encrypt生成的证书文件

1
2
3
4
5
6
7
sudo docker container run \
--name mynginx \
--rm \
--volume "$PWD/conf":/etc/nginx \
-v /etc/letsencrypt:/etc/letsencrypt/ \
-d \
nginx

-v : 映射本地/etc/letsencrypt到容器/etc/letsencrypt目录。

HTTPS 配置

配置conf/conf.d/default.conf文件,具体配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
server {
listen 80;
server_name www.shiyx.top;
return 301 https://www.shiyx.top$request_uri;
server_tokens off;
}
server {
listen 443 ssl http2;
ssl on;
server_name www.shiyx.top;
#$host该变量的值等于请求头中Host的值。如果Host无效时,那么就是处理该请求的server的名称。
#permanent: 永久性重定向。请求日志中的状态码为301
#nginx 对文档检测比较严格,所以if ( $host != 'www.csdn.com' ) 这些代码之间需要有空格隔开,不然会
#报错:unknown directive “if($host!=”
if ($host != 'www.shiyx.top' ){
rewrite ^/(.*)$ https://www.shiyx.top/$1 permanent;
}
ssl_certificate /etc/letsencrypt/live/shiyx.top/fullchain.pem;

ssl_certificate_key /etc/letsencrypt/live/shiyx.top/privkey.pem;

#禁止在header中出现服务器版本,防止黑客利用版本漏洞攻击
server_tokens off;
# 设置ssl/tls会话缓存的类型和大小。如果设置了这个参数一般是shared,buildin可能会参数内存碎片,默认是none,
#和off差不多,停用缓存。如shared:SSL:10m表示我>所有的nginx工作进程共享ssl会话缓存,
#网介绍说1M可以存放约4000个sessions。
ssl_session_cache shared:SSL:1m;

# 客户端可以重用会话缓存中ssl参数的过期时间,内网系统默认5分钟太短了,可以设成30m即30分钟甚至4h。
ssl_session_timeout 5m;

ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;

# 选择加密套件,不同的浏览器所支持的套件(和顺序)可能会不同。
# 这里指定的是OpenSSL库能够识别的写法,你可以通过 openssl -v cipher 'RC4:HIGH:!aNULL:!MD5'
#(后面是你所指定的套件加密算法) 来看所支持算法。
ssl_ciphers HIGH:!aNULL:!MD5;

# 设置协商加密算法时,优先使用我们服务端的加密套件,而不是客户端浏览器的加密套件。
ssl_prefer_server_ciphers on;

# 查看代理程序的ip
# sudo docker inspect --format '{{ .NetworkSettings.IPAddress }}' <container-ID>
location / {
proxy_pass http://172.17.0.3:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
}
location ~ /.well-known{
allow all;
}
}

查看docker ip地址

1
sudo docker inspect --format '{{ .NetworkSettings.IPAddress }}' <container-ID>

最后,启动一个新的Nginx容器。

** 注意运行目录**

1
2
3
4
5
6
7
8
9
sudo docker container run \
--name mynginx \
--rm \
--volume "$PWD/conf":/etc/nginx \
-v /etc/letsencrypt:/etc/letsencrypt/ \
-p 80:80 \
-p 443:443 \
-d \
nginx

参考:
http://www.ruanyifeng.com/blog/2018/02/nginx-docker.html

https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-nginx?view=aspnetcore-2.0&tabs=aspnetcore2x

http://www.cnblogs.com/savorboard/p/dotnet-core-publish-nginx.html

DotNetCore使用Docker部署

docker安装(ubuntu16.04)

1
2
sudo apt-get update
sudo apt-get install docker-ce

拉取microsoft/dotnet镜像

1
2
3
4
5
6
7
8
9
10
11
12
ubuntu@ip-172-31-16-20:~$ sudo docker pull microsoft/dotnet
Using default tag: latest
latest: Pulling from microsoft/dotnet
cc1a78bfd46b: Pull complete
6861473222a6: Pull complete
7e0b9c3b5ae0: Pull complete
3ec98735f56f: Pull complete
8b3d41e9a6c9: Pull complete
92c2ea8451ce: Pull complete
e321ed356c13: Pull complete
Digest: sha256:ec26f9d34e3e8a85eb3f0d269170e5502bdee7d1ed46ddc1356d9ba6d245e6fa
Status: Downloaded newer image for microsoft/dotnet:latest

运行microsoft/dotnet镜像

使用docker run <image>可以启动镜像,通过指定参数-it以交互模式(进入容器内部)启动
--rm 退出时,删除容器。

1
2
3
4
5
6
7
8
9
10
11
//启动一个dotnet镜像
$ docker run --rm -it microsoft/dotnet

//创建项目名为docker.Web的.NET Core MVC项目
dotnet new mvc -n docker.web

//进入docker.web文件夹
cd docker.web

//启动.NET Core MVC项目
dotnet run

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
ubuntu@ip-172-31-16-20:~$ sudo docker run --rm -it microsoft/dotnet
root@b2ce07e9f5e5:/# dotnet new mvc -n docker.web
The template "ASP.NET Core Web App (Model-View-Controller)" was created successfully.
This template contains technologies from parties other than Microsoft, see https://aka.ms/template-3pn for details.

Processing post-creation actions...
Running 'dotnet restore' on docker.web/docker.web.csproj...
Restoring packages for /docker.web/docker.web.csproj...
Generating MSBuild file /docker.web/obj/docker.web.csproj.nuget.g.props.
Generating MSBuild file /docker.web/obj/docker.web.csproj.nuget.g.targets.
Restore completed in 1.69 sec for /docker.web/docker.web.csproj.
Restoring packages for /docker.web/docker.web.csproj...
Restore completed in 338.5 ms for /docker.web/docker.web.csproj.

Restore succeeded.

root@b2ce07e9f5e5:/# cd docker.web
root@b2ce07e9f5e5:/docker.web# dotnet run
warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
No XML encryptor configured. Key {392f49bb-6372-47a0-a34b-94b82a079812} may be persisted to storage in unencrypted form.
warn: Microsoft.AspNetCore.Server.Kestrel[0]
Unable to bind to http://localhost:5000 on the IPv6 loopback interface: 'Error -99 EADDRNOTAVAIL address not available'.
Hosting environment: Production
Content root path: /docker.web
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.

挂载源代码

宿主机安装.NET Core SDK

1
2
3
4
5
wget -q packages-microsoft-prod.deb https://packages.microsoft.com/config/ubuntu/16.04/packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
sudo apt-get install apt-transport-https
sudo apt-get update
sudo apt-get install dotnet-sdk-2.1.200

安装完毕后,我们依次执行以下命令创建一个.NET Core MVC项目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//回到根目录
$ cd $HOME

//创建demo文件夹
$ mkdir demo
$ cd demo

//创建项目名为docker.web的.NET Core MVC项目
sudo dotnet new mvc -n docker.web

//进入docker.web文件夹
cd docker.web

//启动.NET Core MVC项目
sudo dotnet run

sudo lsof -i :5000:查看5000端口信息

挂载宿主机项目到容器中

在启动Docker镜像时,Docker允许我们通过使用-v参数挂载宿主机的文件到容器的指定目录下。

1
2
3
4
// 命令中的`\`结合`Enter`键构成换行符,允许我们换行输入一个长命令。
$ sudo docker run --rm -it \
-v $HOME/dotnet/docker.web:/app \
microsoft/dotnet:latest

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
ubuntu@ip-172-31-16-20:~$ sudo docker run --rm -it \
> -v $HOME/dotnet/docker.web:/app \
> microsoft/dotnet:latest
root@4e0ae54991c4:/# ls
app boot etc lib media opt root sbin sys usr
bin dev home lib64 mnt proc run srv tmp var
root@4e0ae54991c4:/# cd app
root@4e0ae54991c4:/app# ls
Controllers Startup.cs appsettings.json docker.web.csproj
Models Views bin obj
Program.cs appsettings.Development.json bundleconfig.json wwwroot
root@4e0ae54991c4:/app# dotnet run
warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
No XML encryptor configured. Key {3600e0ea-f9cc-4c43-b75f-58665338c060} may be persisted to storage in unencrypted form.
warn: Microsoft.AspNetCore.Server.Kestrel[0]
Unable to bind to http://localhost:5000 on the IPv6 loopback interface: 'Error -99 EADDRNOTAVAIL address not available'.
Hosting environment: Production
Content root path: /app
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.

上面说到是以共享的形式,而不是容器拥有一份宿主机目录的拷贝,意味着,在宿主机上对目录的更改,会即时反应到容器中。但反过来,容器中对共享目录的更改,不会反应到宿主机上,不然就打破了容器具有的隔离特性。

使用Dockerfile部署

Dockerfile用来定义你将要在容器中执行的系列操作。我们来创建一个Dockerfile:

1
2
3
4
5
6
7
8
//确保进入我们创建的MVC项目目录中去
$ cd $HOME/demo/HelloDocker.Web

//使用touch命令创建Dockerfile
$ sudo touch Dockerfile

//使用vi命令编辑Dockerfile
sudo vim Dockerfile

填入以下内容:

1
2
3
4
5
6
7
FROM microsoft/dotnet:latest
WORKDIR /app
COPY . /app
RUN dotnet restore
EXPOSE 5000
ENV ASPNETCORE_URLS http://*:5000
ENTRYPOINT ["dotnet","run"]

wq:保存退出

1
2
3
4
5
6
7
FROM:指定容器使用的镜像
WORKDIR:指定工作目录
COPY:复制当前目录(其中.即代表当前目录)到容器中的/app目录下
RUN:命令指定容器中执行的命令
EXPOSE:指定容器暴露的端口号
ENV:指定环境参数,上面用来告诉.NETCore项目在所有网络接口上监听5000端口
ENTRYPOINT:制定容器的入口点

使用docker build -t <name> <path>指令打包镜像:

1
docker build -t docker.web .

.:表示当前路径

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
ubuntu@ip-172-31-16-20:~/dotnet/docker.web$ sudo docker build -t docker.web .
Sending build context to Docker daemon 4.937MB
Step 1/7 : FROM microsoft/dotnet:latest
---> 2ac9a416f201
Step 2/7 : WORKDIR /app
Removing intermediate container 921079b99047
---> 9449738bc5a1
Step 3/7 : COPY . /app
---> b64089162379
Step 4/7 : RUN dotnet restore
---> Running in 0f13fc033144
Restore completed in 76.09 ms for /app/docker.web.csproj.
Restoring packages for /app/docker.web.csproj...
Restore completed in 499.14 ms for /app/docker.web.csproj.
Removing intermediate container 0f13fc033144
---> 31a054861344
Step 5/7 : EXPOSE 5000
---> Running in 2a87ea69cb01
Removing intermediate container 2a87ea69cb01
---> 83e3c278ae44
Step 6/7 : ENV ASPNETCORE_URLS http://*:5000
---> Running in 535c7da1ced9
Removing intermediate container 535c7da1ced9
---> 4965bd215b81
Step 7/7 : ENTRYPOINT ["dotnet","run"]
---> Running in d023e6d8160b
Removing intermediate container d023e6d8160b
---> eb265d4f49cd
Successfully built eb265d4f49cd
Successfully tagged docker.web:latest

运行新打包的镜像,并通过-p参数映射容器的5000到宿主机的80端口,其中-d参数告诉docker以后台任务形式运行镜像,--rm退出时删除容器,--name指定容器名称。

1
sudo docker run --name dockerweb -d --rm -p 80:5000 docker.web

通过curl -i http://localhost验证。

1
2
3
4
5
6
7
8
9
10
11
12
13
ubuntu@ip-172-31-16-20:~$ curl -i http://localhost
HTTP/1.1 200 OK
Date: Tue, 15 May 2018 05:43:45 GMT
Content-Type: text/html; charset=utf-8
Server: Kestrel
Transfer-Encoding: chunked

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Home Page - docker.web</title>

至此,完成dotnetcore项目部署。

参考:

http://www.cnblogs.com/sheng-jie/p/8107877.html#autoid-4-0-0

http://www.cnblogs.com/savorboard/p/dotnetcore-docker.html

Docker Compose配置文件详解

参考官网:https://docs.docker.com/compose/compose-file/#service-configuration-reference

Compose文件是一个定义服务, 网络和 卷的YAML文件 。Compose文件的默认路径是。./docker-compose.yml

标准配置文件应该包含 version、services、networks 三大部分,其中最关键的就是 services 和 networks 两个部分。

提示:您可以对此文件使用a .yml或.yaml扩展名。他们都工作。

image

1
2
3
services:
dotnetcoreapp1:
image: dotnetcoreapp

在 services 标签下的第二级标签是 dotnetcoreapp1,这个名字是用户自己自定义,它就是服务名称。

image 则是指定服务的镜像名称或镜像 ID。如果镜像在本地不存在,Compose 将会尝试拉取这个镜像。

build

在构建时应用的配置选项

build 可以指定为构建上下文的路径:

1
2
3
4
version: '3'
services:
webapp:
build: ./dir
1
2
3
4
5
6
7
8
version: '3'
services:
webapp:
build:
context: ./dir
dockerfile: Dockerfile-alternate
args:
buildno: 1

如果同时指定build和image,那么会在./dir中生成名为webapp和标记的镜像tag。

context

可以是包含Dockerfile的目录的路径,也可以是到git存储库的URL。

当提供的值是相对路径时,它被解释为相对于撰写文件的位置。 这个目录也是发送到Docker守护进程的构建上下文。

使用生成的名称构建并标记它,然后使用该镜像。

1
2
build:
context: ./dir

dockerfile

dockerfile作为备用,并且需要提供路径。

1
2
3
build:
context: .
dockerfile: Dockerfile-alternate

args

添加构建参数,这些参数是仅在构建过程中可访问的环境变量。

首先,指定Dockerfile:

1
2
3
4
5
ARG buildno
ARG gitcommithash

RUN echo "Build number: $buildno"
RUN echo "Based on commit: $gitcommithash"

然后指定参数。 您可以传递一个映射或一个列表:

1
2
3
4
5
6
7
8
9
10
11
build:
context: .
args:
buildno: 1
gitcommithash: cdc3b19

build:
context: .
args:
- buildno=1
- gitcommithash=cdc3b19

指定构建参数时可以省略该值,在这种情况下,构建时的值是构成运行环境中的值。

1
2
3
args:
- buildno
- gitcommithash

注意:YAML 的布尔值(true, false, yes, no, on, off)必须要使用引号引起来(单引号、双引号均可),否则会当成字符串解析。

cache_from

v3.2新添加

用于缓存解析的镜像列表

1
2
3
4
5
build:
context: .
cache_from:
- alpine:latest
- corp/web_app:3.14

labels

v3.3新添加

使用Docker标签将元数据添加到生成的图像。 您可以使用数组或字典。

建议您使用反向DNS标记来防止您的标签与其他软件使用的标签冲突。

1
2
3
4
5
6
7
8
9
10
11
12
13
build:
context: .
labels:
com.example.description: "Accounting webapp"
com.example.department: "Finance"
com.example.label-with-empty-value: ""

build:
context: .
labels:
- "com.example.description=Accounting webapp"
- "com.example.department=Finance"
- "com.example.label-with-empty-value"

shm_size

v3.5新添加

为此版本的容器设置/dev/shm分区的大小。 指定为表示字节数的整数值或表示字节值的字符串。

1
2
3
4
5
6
7
build:
context: .
shm_size: '2gb'

build:
context: .
shm_size: 10000000

cap_add, cap_drop

添加或删除容器功能

1
2
3
4
5
6
cap_add:
- ALL

cap_drop:
- NET_ADMIN
- SYS_ADMIN

command

command 覆盖容器启动后默认执行的命令

1
command: bundle exec thin -p 3000

该命令也可以是一个列表,方式类似于dockerfile:

1
command: ["bundle", "exec", "thin", "-p", "3000"]

configs

configs命令

Grant access to configs on a per-service basis using the per-service configs configuration.

为每个服务配置配置为每个服务授予对配置的访问权限。支持两种不同的语法变体。

注意:配置必须已经存在或在此堆栈文件的顶级配置配置中定义,否则堆栈部署失败。

SHORT SYNTAX

简短的语法变体只能指定配置​​名称

支持v3.3以上

以下示例使用简短语法将redis服务访问权限授予my_config和my_other_config配置。 my_config的值被设置为文件./my_config.txt的内容,my_other_config被定义为外部资源,这意味着它已经在Docker中定义,可以通过运行docker config create命令或通过另一个堆栈部署。如果外部配置不存在,堆栈部署将失败并显示配置未找到错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
version: "3.3"
services:
redis:
image: redis:latest
deploy:
replicas: 1
configs:
- my_config
- my_other_config
configs:
my_config:
file: ./my_config.txt
my_other_config:
external: true

LONG SYNTAX

长的语法提供了在服务的任务容器中如何创建配置的更细粒度。

source:Docker中配置的名称。

target:要在服务的任务容器中安装的文件的路径和名称。如果未指定,则默认为 /<source>

uid和gid:在服务的任务容器中拥有安装的配置文件的数字UID或GID。如果未指定,则在Linux上均默认为0。 Windows不支持。

mode:安装在服务任务容器内的文件的权限,采用八进制表示法。例如,0444代表可读。缺省值为0444.由于Configs被挂载在临时文件系统中,因此它们不能写入,因此如果设置了可写位,它将被忽略。可执行位可以被设置。如果您不熟悉UNIX文件权限模式,则可能会发现此权限计算器很有用。

以下示例将容器中my_config的名称设置为redis_config,将模式设置为0440(可读组),并将用户和组设置为103. redis服务无法访问my_other_config配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
version: "3.3"
services:
redis:
image: redis:latest
deploy:
replicas: 1
configs:
- source: my_config
target: /redis_config
uid: '103'
gid: '103'
mode: 0440
configs:
my_config:
file: ./my_config.txt
my_other_config:
external: true

您可以授予多个配置的服务访问权限,您可以混合使用长短语法。定义配置并不意味着授予服务访问权限。

container_name

指定自定义容器名称

由于Docker容器名称必须是唯一的,因此如果您指定了自定义名称,则无法将服务扩展到1个容器之外。 试图这样做会导致错误。

1
container_name: my-web-container

注意:当使用(版本3)Compose文件在群集模式下部署堆栈时,忽略此选项。

deploy

指定与部署和运行服务相关的配置。 这只在部署到使用docker stack部署的群集时才生效,并且被docker-compose up和docker-compose run忽略。

1
2
3
4
5
6
7
8
9
10
11
version: '3'
services:
redis:
image: redis:alpine
deploy:
replicas: 6
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure

ENDPOINT_MODE

指定连接到群组的外部客户端的服务发现方法。

v3.3独有

endpoint_mode:vip - Docker为服务分配一个虚拟IP(VIP),作为客户端到达网络服务的“前端”。 Docker在客户端和可用的工作节点之间为服务路由请求,而客户端不知道有多少节点参与服务或其IP地址或端口。 (这是默认设置。)

endpoint_mode:dnsrr - DNS轮询(DNSRR)服务发现不使用单个虚拟IP。 Docker为服务设置DNS条目,使得服务名称的DNS查询返回一个IP地址列表,并且客户端直接连接到其中的一个。 如果您想使用自己的负载平衡器,或者混合Windows和Linux应用程序,则DNS轮询功能非常有用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
version: "3.3"

services:
wordpress:
image: wordpress
ports:
- "8080:80"
networks:
- overlay
deploy:
mode: replicated
replicas: 2
endpoint_mode: vip

mysql:
image: mysql
volumes:
- db-data:/var/lib/mysql/data
networks:
- overlay
deploy:
mode: replicated
replicas: 2
endpoint_mode: dnsrr

volumes:
db-data:

networks:
overlay:

docker service create

LABELS

指定服务的标签。 这些标签仅在服务上设置,而不在服务的任何容器上设置。

1
2
3
4
5
6
7
version: "3"
services:
web:
image: web
deploy:
labels:
com.example.description: "This label will appear on the web service"

要在容器上设置标签,请在部署之外使用标签键:

1
2
3
4
5
6
version: "3"
services:
web:
image: web
labels:
com.example.description: "This label will appear on all containers for the web service"

MODE

全局(每个群集节点只有一个容器)或复制(指定数量的容器)。 默认值被复制。 (要了解更多信息,请参阅swarm主题中的复制和全局服务。)

1
2
3
4
5
6
version: '3'
services:
worker:
image: dockersamples/examplevotingapp_worker
deploy:
mode: global

PLACEMENT

指定约束和偏好的位置。

1
2
3
4
5
6
7
8
9
10
11
version: '3.3'
services:
db:
image: postgres
deploy:
placement:
constraints:
- node.role == manager
- engine.labels.operatingsystem == ubuntu 14.04
preferences:
- spread: node.labels.zone

REPLICAS

如果服务被复制(这是默认设置),请指定在任何给定时间应该运行的容器数量。

1
2
3
4
5
6
7
8
9
10
version: '3'
services:
worker:
image: dockersamples/examplevotingapp_worker
networks:
- frontend
- backend
deploy:
mode: replicated
replicas: 6

RESOURCES

配置资源限制。

注意:这会替换版本3之前的Compose文件(cpu_shares,cpu_quota,cpuset,mem_limit,memswap_limit,mem_swappiness)中的非群集模式的旧资源约束选项,如升级2.x版至3.x中所述。

在这个一般的例子中,Redis服务限制使用不超过50M的内存和0.50(50%)的可用处理时间(CPU),并且具有20M的内存和0.25个CPU时间保留(总是可用)。

1
2
3
4
5
6
7
8
9
10
11
12
version: '3'
services:
redis:
image: redis:alpine
deploy:
resources:
limits:
cpus: '0.50'
memory: 50M
reservations:
cpus: '0.25'
memory: 20M

这里描述的选项特定于部署密钥和群集模式。 如果要为非群部署设置资源约束,请使用Compose文件格式版本2 CPU,内存和其他资源选项。

** 内存异常(OOME)**
如果您的服务或容器尝试使用比系统可用的内存更多的内存,则可能会遇到内存异常(OOME),并且容器或Docker守护程序可能会被内核OOM杀手所杀。 要防止发生这种情况,请确保您的应用程序在具有足够内存的主机上运行,并且请参阅了解耗尽内存的风险。

RESTART_POLICY

配置是否以及如何在退出时重新启动容器。 取代重新启动。

condition:无,失败或任何(默认:任何)。
delay:在重启尝试之间等待多长时间,指定为持续时间(默认值:0)。
max_attempts:放弃之前尝试重新启动容器的次数(默认值:永不放弃)。 如果重新启动在配置的窗口内没有成功,则此尝试不计入配置的max_attempts值。 例如,如果max_attempts设置为’2’,并且第一次尝试重新启动失败,则可能会尝试重新启动两次以上。
window:在决定重新启动是否成功之前等待多久,指定为持续时间(默认值:立即决定)。

1
2
3
4
5
6
7
8
9
10
version: "3"
services:
redis:
image: redis:alpine
deploy:
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s

UPDATE_CONFIG

配置如何更新服务。 用于配置滚动更新。

parallelism:一次更新容器的数量。
delay:更新一组容器之间的等待时间。
failure_action:更新失败时该怎么做。 继续,回滚或暂停之一(默认:暂停)。
monitor:每次任务更新后监视失败的时间(ns | us | ms | s | m | h)(默认为0)。
max_failure_ratio:在更新期间容忍的失败率。
order:更新期间的操作顺序。 停止优先(旧任务在开始新任务之前停止)或者先启动(首先启动新任务,并且正在运行的任务短暂重叠)(默认停止优先)注意:只支持v3.4及更高版本。

order支持v3.4或更高版本

1
2
3
4
5
6
7
8
9
10
11
12
version: '3.4'
services:
vote:
image: dockersamples/examplevotingapp_vote:before
depends_on:
- redis
deploy:
replicas: 2
update_config:
parallelism: 2
delay: 10s
order: stop-first

devices

设备映射列表。 使用与–device docker客户端创建选项相同的格式。

1
2
devices:
- "/dev/ttyUSB0:/dev/ttyUSB0"

注意:当使用(版本3)Compose文件在群集模式下部署堆栈时,忽略此选项。

depends_on

服务之间的快速依赖关系,服务依赖关系导致以下行为:

docker-compose up 以依赖顺序启动服务。 在以下示例中,db和redis在web之前启动。

docker-up up SERVICE 自动包含SERVICE的依赖关系。 在下面的例子中,docker-compose up web也会创建并启动db和redis。

1
2
3
4
5
6
7
8
9
10
11
version: '3'
services:
web:
build: .
depends_on:
- db
- redis
redis:
image: redis
db:
image: postgres

使用depends_on时有几件事要注意:

在启动web之前,depends_on不会等待db和redis“准备就绪” - 只有在它们启动之前。 如果您需要等待服务准备就绪,请参阅控制启动顺序以了解有关此问题的更多信息以及解决此问题的策略。

版本3不再支持depends_on的条件形式。

使用版本3撰写文件在群集模式下部署堆栈时,将忽略depends_on选项。

dns

自定义DNS服务器。 可以是单个值或列表。

1
2
3
4
dns: 8.8.8.8
dns:
- 8.8.8.8
- 9.9.9.9

自定义DNS搜索域。 可以是单个值或列表。

1
2
3
4
dns_search: example.com
dns_search:
- dc1.example.com
- dc2.example.com

tmpfs

v2.0以上

在容器中装入一个临时文件系统。 可以是单个值或列表。

1
2
3
4
tmpfs: /run
tmpfs:
- /run
- /tmp

注意:在使用(版本3-3.5)撰写文件的群集模式下部署堆栈时,忽略此选项。

v3.6以上

在容器中装入一个临时文件系统。 Size参数以字节为单位指定tmpfs安装的大小。 无限制默认。

1
2
3
4
- type: tmpfs
target: /app
tmpfs:
size: 1000

entrypoint

1
entrypoint: /code/entrypoint.sh
1
2
3
4
5
6
7
entrypoint:
- php
- -d
- zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20100525/xdebug.so
- -d
- memory_limit=-1
- vendor/bin/phpunit

注意:设置入口点都会使用ENTRYPOINT Dockerfile指令覆盖服务映像上设置的任何默认入口点,并清除映像上的任何默认命令 - 这意味着如果Dockerfile中存在CMD指令,则它将被忽略。

env_file

从文件添加环境变量。 可以是单个值或列表。

如果您已经使用docker-compose -f FILE指定了Compose文件,则env_file中的路径与该文件所在的目录相关。

环境部分中声明的环境变量会覆盖这些值 - 即使这些值为空或未定义,也是如此。

1
2
3
4
5
6
env_file: .env

env_file:
- ./common.env
- ./apps/web.env
- /opt/secrets.env

撰写Compose env文件中的每行都是VAR = VAL格式。 以#开始的行被视为注释并被忽略。 空行也被忽略。

1
2
# Set Rails/Rack environment
RACK_ENV=development

注意:如果您的服务指定了构建选项,则在构建期间,环境文件中定义的变量不会自动显示。 使用build的args子选项来定义构建时环境变量。

定义的值并不会始终保持不变,列表中的值按照顺序执行,以最后值为准。

environment

添加环境变量。 您可以使用数组或字典。

任何布尔值; true, false, yes no,需要用引号括起来以确保它们不被YML解析器转换为True或False。

1
2
3
4
5
6
7
8
9
 environment:
RACK_ENV: development
SHOW: 'true'
SESSION_SECRET:

environment:
- RACK_ENV=development
- SHOW=true
- SESSION_SECRET

注意:如果您的服务指定了构建选项,则在构建过程中定义的变量不会自动显示。 使用build的args子选项来定义构建时环境变量。

expose

公开端口而不将它们发布到主机 - 它们只能被链接服务访问。 只能指定内部端口。

1
2
3
expose:
- "3000"
- "8000"

链接到此Docker-compose.yml之外甚至Compose之外的容器,尤其是提供共享或公共服务的容器。 在指定容器名称和链接别名(CONTAINER:ALIAS)时,external_links遵循类似于旧版选项链接的语义。

1
2
3
4
external_links:
- redis_1
- project_db_1:mysql
- project_db_1:postgresql

extra_hosts

添加主机名映射。 使用与docker客户端–add-host参数相同的值。

1
2
3
extra_hosts:
- "somehost:162.242.195.82"
- "otherhost:50.31.209.229"

具有ip地址和主机名的条目在容器内的/etc/hosts中为该服务创建,例如:

1
2
162.242.195.82  somehost
50.31.209.229 otherhost

healthcheck

v2.1以上

配置运行的检查以确定此服务的容器是否“健康”。 查看HEALTHCHECK Dockerfile指令的文档以获取有关健康检查如何工作的详细信息。

1
2
3
4
5
6
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 1m30s
timeout: 10s
retries: 3
start_period: 40s
1
2
3
4
5
6
# Hit the local web app
test: ["CMD", "curl", "-f", "http://localhost"]

# As above, but wrapped in /bin/sh. Both forms below are equivalent.
test: ["CMD-SHELL", "curl -f http://localhost || exit 1"]
test: curl -f https://localhost || exit 1

要禁用图像设置的任何默认健康检查,您可以使用disable:true。 这相当于指定测试:[“NONE”]。

1
2
healthcheck:
disable: true

Specifying durations

一些配置选项(如检查的间隔和超时子选项)以如下格式的字符串形式接受持续时间:

1
2
3
4
5
2.5s
10s
1m30s
2h32m
5h34m56s

支持的单位是us,ms,s,m和h。

isolation

指定容器的隔离技术。 在Linux上,唯一支持的值是默认值。 在Windows上,可接受的值是默认值,进程和hyperv。 有关详细信息,请参阅Docker Engine文档。

labels

使用Docker标签将元数据添加到容器。 您可以使用数组或字典。

建议您使用反向DNS标记来防止您的标签与其他软件使用的标签冲突。

1
2
3
4
5
6
7
8
9
labels:
com.example.description: "Accounting webapp"
com.example.department: "Finance"
com.example.label-with-empty-value: ""

labels:
- "com.example.description=Accounting webapp"
- "com.example.department=Finance"
- "com.example.label-with-empty-value"

logging

记录服务的配置。

1
2
3
4
logging:
driver: syslog
options:
syslog-address: "tcp://192.168.0.42:123"

驱动程序名称指定服务容器的日志记录驱动程序,与docker run的–log-driver选项(此处记录)一样。

默认值是json-file。

1
2
3
driver: "json-file"
driver: "syslog"
driver: "none"

注意:只有json-filejournald驱动程序才能使日志直接从docker-compose updocker-compose logs。 使用任何其他驱动程序不会打印任何日志。

使用选项键指定日志记录驱动程序的日志记录选项,就像docker run的–log-opt选项一样。

1
2
3
driver: "syslog"
options:
syslog-address: "tcp://192.168.0.42:123"

默认驱动程序json-file具有限制存储日志量的选项。 为此,请使用键值对来获得最大存储大小和最大文件数量:

1
2
3
options:
max-size: "200k"
max-file: "10"

上面显示的示例将存储日志文件,直到它们达到200kB的最大大小,然后旋转它们。 存储的单个日志文件的数量由最大文件值指定。 随着日志增长超出最大限制,旧日志文件将被删除以允许存储新日志。

以下是限制日志存储的示例docker-compose.yml文件:

1
2
3
4
5
6
7
8
services:
some-service:
image: some-service
logging:
driver: "json-file"
options:
max-size: "200k"
max-file: "10"

network_mode

网络模式。 使用与docker客户端相同的值–net参数,以及特殊的表单服务:[服务名称]。

1
2
3
4
5
network_mode: "bridge"
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"

network_mode:“host”不能与链接混合使用。

networks

加入网络,引用顶级网络密钥下的条目。

1
2
3
4
5
services:
some-service:
networks:
- some-network
- other-network

ALIASES

网络上此服务的别名(备用主机名)。 同一网络上的其他容器可以使用服务名称或别名来连接到某个服务的容器。

由于别名是网络范围的,相同的服务可以在不同的网络上具有不同的别名。

注意:网络范围的别名可以由多个容器共享,甚至可以由多个服务共享。 如果是,那么名称解析的确切容器的名称就不能保证。

1
2
3
4
5
6
7
8
9
10
services:
some-service:
networks:
some-network:
aliases:
- alias1
- alias3
other-network:
aliases:
- alias2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
version: '2'

services:
web:
build: ./web
networks:
- new

worker:
build: ./worker
networks:
- legacy

db:
image: mysql
networks:
new:
aliases:
- database
legacy:
aliases:
- mysql

networks:
new:
legacy:

IPV4_ADDRESS, IPV6_ADDRESS

加入网络时,为此服务的容器指定一个静态IP地址。

顶级网络部分中的相应网络配置必须具有覆盖每个静态地址的具有子网配置的ipam块。 如果需要IPv6寻址,则必须设置enable_ipv6选项,并且必须使用版本2.x Compose文件,如下所示。

注意:这些选项目前不在群集模式下工作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
version: '2.1'

services:
app:
image: busybox
command: ifconfig
networks:
app_net:
ipv4_address: 172.16.238.10
ipv6_address: 2001:3984:3989::10

networks:
app_net:
driver: bridge
enable_ipv6: true
ipam:
driver: default
config:
-
subnet: 172.16.238.0/24
-
subnet: 2001:3984:3989::/64

pid

1
pid: "host"

将PID模式设置为主机PID模式。 这将打开容器与主机操作系统之间的共享PID地址空间。 使用此标志启动的容器可以访问和操作裸机的名称空间中的其他容器,反之亦然。

ports

公开端口

注意:端口映射与network_mode:host不兼容

SHORT SYNTAX

既可以指定两个端口(HOST:CONTAINER),也可以指定容器端口(选择临时主机端口)。

注意:以HOST:CONTAINER格式映射端口时,使用低于60的容器端口时可能会遇到错误结果,因为YAML会将格式为xx:yy的数字解析为基数为60的值。 出于这个原因,我们建议始终明确指定您的端口映射为字符串。

1
2
3
4
5
6
7
8
9
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"

LONG SYNTAX

长格式语法允许配置不能以简短形式表示的附加字段。

target:容器内的端口
published:公开曝光的港口
protocol:端口协议(tcp或udp)
mode:用于在每个节点上发布主机端口的主机,或用于群集模式端口的入口以进行负载平衡。

1
2
3
4
5
ports:
- target: 80
published: 8080
protocol: tcp
mode: host

注意:长语法在v3.2中是新的

secrets

1
2
3
4
5
6
7
8
9
10
11
12
13
14
version: "3.1"
services:
redis:
image: redis:latest
deploy:
replicas: 1
secrets:
- my_secret
- my_other_secret
secrets:
my_secret:
file: ./my_secret.txt
my_other_secret:
external: true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
version: "3.1"
services:
redis:
image: redis:latest
deploy:
replicas: 1
secrets:
- source: my_secret
target: redis_secret
uid: '103'
gid: '103'
mode: 0440
secrets:
my_secret:
file: ./my_secret.txt
my_other_secret:
external: true

security_opt

覆盖每个容器的默认标签方案。

1
2
3
security_opt:
- label:user:USER
- label:role:ROLE

stop_grace_period

指定在发送SIGKILL之前,如果试图停止一个容器(如果它没有处理SIGTERM)(或者使用stop_signal指定了任何停止信号),请等待多久。 指定为持续时间。

1
2
stop_grace_period: 1s
stop_grace_period: 1m30s

默认情况下,停止在发送SIGKILL之前等待10秒钟容器退出。

stop_signal

设置一个替代信号来停止容器。 默认停止使用SIGTERM。 使用stop_signal设置替代信号会导致停止发送该信号。

1
stop_signal: SIGUSR1

sysctls

在容器中设置的内核参数。 您可以使用数组或字典。

1
2
3
4
5
6
7
sysctls:
net.core.somaxconn: 1024
net.ipv4.tcp_syncookies: 0

sysctls:
- net.core.somaxconn=1024
- net.ipv4.tcp_syncookies=0

ulimits

覆盖容器的默认限制。 您可以将单个限制指定为整数,也可以将软限制/硬限制指定为映射。

1
2
3
4
5
ulimits:
nproc: 65535
nofile:
soft: 20000
hard: 40000

userns_mode

1
userns_mode: "host"

如果Docker守护程序配置了用户命名空间,则禁用此服务的用户命名空间。

volumes

装载主机路径或命名卷,将其指定为服务的子选项。

您可以将主机路径作为单个服务的定义的一部分进行安装,并且无需在顶级卷密钥中定义它。

但是,如果要跨多个服务重用卷,请在顶级卷密钥中定义一个命名卷。 将命名卷与服务,群集和堆栈文件一起使用。

注意:顶级卷密钥定义了一个命名卷,并从每个服务的卷列表中引用它。 这会替换早期版本的Compose文件格式中的volumes_from。 有关卷的一般信息,请参阅使用卷和卷插件。

此示例显示Web服务正在使用的命名卷(mydata),以及为单个服务(数据库服务卷下的第一个路径)定义的绑定挂载。 数据库服务还使用名为dbdata的命名卷(数据库服务卷下的第二个路径),但使用旧的字符串格式定义它以装载命名卷。 如图所示,命名卷必须列在顶级卷密钥下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
version: "3.2"
services:
web:
image: nginx:alpine
volumes:
- type: volume
source: mydata
target: /data
volume:
nocopy: true
- type: bind
source: ./static
target: /opt/app/static

db:
image: postgres:latest
volumes:
- "/var/run/postgres/postgres.sock:/var/run/postgres/postgres.sock"
- "dbdata:/var/lib/postgresql/data"

volumes:
mydata:
dbdata:

SHORT SYNTAX

可以选择在主机上(HOST:CONTAINER)或访问模式(HOST:CONTAINER:ro)指定路径。

您可以在主机上挂载相对路径,该路径相对于正在使用的Compose配置文件的目录进行扩展。 相对路径应始终以

...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
volumes:
# Just specify a path and let the Engine create a volume
- /var/lib/mysql

# Specify an absolute path mapping
- /opt/data:/var/lib/mysql

# Path on the host, relative to the Compose file
- ./cache:/tmp/cache

# User-relative path
- ~/configs:/etc/configs/:ro

# Named volume
- datavolume:/var/lib/mysql

LONG SYNTAX

type:装载类型卷,绑定或tmpfs
source:装入源,主机上用于绑定装入的路径或顶级卷密钥中定义的卷的名称。 不适用于tmpfs安装。
target:卷所在的容器中的路径
read_only:标志将卷设置为只读
bind:配置额外的绑定选项
propagation:用于绑定的传播模式
volume:配置额外的volume选项
nocopy:标志,用于在卷创建时禁止从容器复制数据
tmpfs:配置附加的tmpfs选项
size:tmpfs的大小,以字节为单位

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
version: "3.2"
services:
web:
image: nginx:alpine
ports:
- "80:80"
volumes:
- type: volume
source: mydata
target: /data
volume:
nocopy: true
- type: bind
source: ./static
target: /opt/app/static

networks:
webnet:

volumes:
mydata:

Note: The long syntax is new in v3.2

** 服务,群集和堆栈文件的卷**

在使用服务,群集和docker-stack.yml文件时,请记住支持服务的任务(容器)可以部署在群集中的任何节点上,并且每次更新服务时都可能是不同的节点。

在缺少指定源的命名卷的情况下,Docker为支持服务的每个任务创建一个匿名卷。关联的容器被移除后,匿名卷不会保留。

如果您希望数据持久存在,请使用可识别多主机的命名卷和卷驱动程序,以便可以从任何节点访问数据。或者,对该服务设置约束,以便将其任务部署在具有该卷的节点上。

作为一个例子,Docker Labs中votingapp示例的docker-stack.yml文件 定义了一个称为运行数据库的服务。它被配置为一个命名卷来保存群体上的数据, 并且仅限于在节点上运行。这是来自该文件的相关剪辑:db postgres manager

1
2
3
4
5
6
7
8
9
10
11
version: "3"
services:
db:
image: postgres:9.4
volumes:
- db-data:/var/lib/postgresql/data
networks:
- backend
deploy:
placement:
constraints: [node.role == manager]

restart

no是默认的重启策略,在任何情况下都不会重启容器。 总是指定时,容器总是重新启动。 如果退出代码指示出现故障错误,则故障中策略会重新启动容器。

1
2
3
4
restart: "no"
restart: always
restart: on-failure
restart: unless-stopped

domainname, hostname, ipc, mac_address, privileged, read_only, shm_size, stdin_open, tty, user, working_dir

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
user: postgresql
working_dir: /code

domainname: foo.com
hostname: foo
ipc: host
mac_address: 02:42:ac:11:65:43

privileged: true


read_only: true
shm_size: 64M
stdin_open: true
tty: true

Specifying durations

一些配置选项(如interval和timeout )以如下格式的字符串形式接受持续时间:

1
2
3
4
5
2.5s
10s
1m30s
2h32m
5h34m56s

Volume configuration reference

虽然可以将文件中的卷声明为服务声明的一部分,但本节允许您创建可在多个服务中重复使用的命名卷(不依赖于volumes_from),并且可以使用docker命令行轻松检索和检查 或API。 有关更多信息,请参阅docker卷子命令文档。

有关卷的一般信息,请参阅使用卷和卷插件。

以下是一个双服务设置的示例,其中数据库的数据目录与另一个服务共享为一个卷,以便可以定期进行备份:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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:

顶级卷密钥下的条目可以为空,在这种情况下,它使用由引擎配置的默认驱动程序(在大多数情况下,这是本地驱动程序)。 或者,您可以使用以下键配置它:

driver

指定应该为此卷使用哪个卷驱动程序。 默认为Docker引擎已经配置使用的驱动程序,在大多数情况下它是本地的。 如果驱动程序不可用,则当docker-compose up尝试创建卷时,引擎会返回错误。

1
driver: foobar

driver_opts

指定一个选项列表作为传递给该卷的驱动程序的键值对。 这些选项是依赖于驱动程序的 - 请查阅驱动程序的文档以获取更多信息。 可选的。

1
2
3
driver_opts:
foo: "bar"
baz: 1

external

如果设置为true,则指定该卷已在Compose之外创建。 docker-compose up不会尝试创建它,并在它不存在时引发错误。

外部不能与其他卷配置键(驱动程序,driver_opts)一起使用。

在下面的示例中,Compose不是试图创建一个名为[projectname] _data的卷,而是查找一个简单称为data的现有卷,并将其挂载到数据库服务的容器中。

1
2
3
4
5
6
7
8
9
10
11
version: '2'

services:
db:
image: postgres
volumes:
- data:/var/lib/postgresql/data

volumes:
data:
external: true

external.name在版本3.4文件格式中被弃用,而使用name。

您还可以在Compose文件中单独指定用于引用它的名称来指定卷的名称:

1
2
3
4
volumes:
data:
external:
name: actual-name-of-volume

** 外部卷始终使用Docker堆栈部署来创建**

如果您使用docker stack deploy以swarm模式启动应用程序(而不是docker组合),则创建不存在的外部卷。 在群集模式下,当服务定义时会自动创建一个卷。 由于服务任务在新节点上进行安排,因此swarmkit会在本地节点上创建卷

labels

使用Docker标签将元数据添加到容器。 您可以使用数组或字典。

建议您使用反向DNS标记来防止您的标签与其他软件使用的标签冲突。

1
2
3
4
5
6
7
8
9
labels:
com.example.description: "Database volume"
com.example.department: "IT/Ops"
com.example.label-with-empty-value: ""

labels:
- "com.example.description=Database volume"
- "com.example.department=IT/Ops"
- "com.example.label-with-empty-value"

name

为此卷设置一个自定义名称。 名称字段可用于引用包含特殊字符的网络。 该名称按原样使用,不会与堆栈名称一起作用。

1
2
3
4
version: '3.4'
volumes:
data:
name: my-app-data
1
2
3
4
5
version: '3.4'
volumes:
data:
external: true
name: my-app-data

chmod命令用于改变linux系统文件或目录的访问权限。用它控制文件或目录的访问权限。
该命令有两种用法:

一种是包含字母和操作符表达式的文字设定法;
一种是包含数字的数字设定法。

Linux系统中的每个文件和目录都有访问许可权限,用它来确定谁可以通过何种方式对文件和目录进行访问和操作。

文件或目录的访问权限分为只读,只写和可执行三种。以文件为例,只读权限表示只允许读其内容,而禁止对其做任何的更改操作。可执行权限表示允许将该文件作为一个程序执行。文件被创建时,文件所有者自动拥有对该文件的读、写和可执行权限,以便于对文件的阅读和修改。用户也可根据需要把访问权限设置为需要的任何组合。

有三种不同类型的用户可对文件或目录进行访问:文件所有者,同组用户、其他用户。所有者一般是文件的创建者。所有者可以允许同组用户有权访问文件,还可以将文件的访问权限赋予系统中的其他用户。在这种情况下,系统中每一位用户都能访问该用户拥有的文件或目录。

每一文件或目录的访问权限都有三组,每组用三位表示,分别为文件属主的读、写和执行权限;与属主同组的用户的读、写和执行权限;系统中其他用户的读、写和执行权限。当用ls -l命令显示文件或目录的详细信息时,最左边的一列为文件的访问权限。 例如:

1
2
3
4
5
[toor@localhost cmdtest]$ ls -al
总用量 4
drwxrwxr-x. 2 toor toor 24 5月 11 09:19 .
drwx------. 15 toor toor 4096 5月 11 09:19 ..
-rw-rw-r--. 1 toor toor 0 5月 11 09:19 2018511.log

以2018511.log为例:

-rw-rw-r--. 1 toor toor 0 5月 11 09:19 2018511.log

第一列共有10个位置,第一个字符指定了文件类型。在通常意义上,一个目录也是一个文件。如果第一个字符是横线,表示是一个非目录的文件。如果是d,表示是一个目录。从第二个字符开始到第十个共9个字符,3个字符一组,分别表示了3组用户对文件或者目录的权限。权限字符用横线代表空许可,r代表只读,w代表写,x代表可执行。

例如:
-rw-rw-r--
  表示2018511.log是一个普通文件;2018511.log的属主有读写权限;与log2012.log属主同组的用户有读写权限;其他用户也只有读权限。

确定了一个文件的访问权限后,用户可以利用Linux系统提供的chmod命令来重新设定不同的访问权限。也可以利用chown命令来更改某个文件或目录的所有者。利用chgrp命令来更改某个文件或目录的用户组。

chmod命令是非常重要的,用于改变文件或目录的访问权限。用户用它控制文件或目录的访问权限。

命令格式

1
chmod [-cfvR] [--help] [--version] mode file

命令功能

用于改变文件或目录的访问权限,用它控制文件或目录的访问权限。

命令参数

必要参数:

1
2
3
4
-c 当发生改变时,报告处理信息
-f 错误信息不输出
-R 处理指定目录以及其子目录下的所有文件
-v 运行时显示详细处理信息

选择参数:

1
2
3
4
5
--reference=<目录或者文件> 设置成具有指定目录或者文件具有相同的权限
--version 显示版本信息
<权限范围>+<权限设置> 使权限范围内的目录或者文件具有指定的权限
<权限范围>-<权限设置> 删除权限范围的目录或者文件的指定权限
<权限范围>=<权限设置> 设置权限范围内的目录或者文件的权限为指定的值

权限范围:

1
2
3
4
u :目录或者文件的当前的用户
g :目录或者文件的当前的群组
o :除了目录或者文件的当前用户或群组之外的用户或者群组
a :所有的用户及群组

权限代号:

1
2
3
4
5
r :读权限,用数字4表示
w :写权限,用数字2表示
x :执行权限,用数字1表示
- :删除权限,用数字0表示
s :特殊权限

该命令有两种用法。一种是包含字母和操作符表达式的文字设定法;另一种是包含数字的数字设定法。

文字设定法:

格式:

1
chmodwho] [+ | - | =] [mode] 文件名

数字设定法

格式:

1
chmod [mode] 文件名

0表示没有权限,1表示可执行权限,2表示可写权限,4表示可读权限,然后将其相加。所以数字属性的格式应为3个从0到7的八进制数,其顺序是(u)(g)(o)。

例如,如果想让某个文件的属主有“读/写”二种权限,需要把4(可读)+2(可写)=6(读/写)。

数字与字符对应关系如下:

r=4,w=2,x=1
若要rwx属性则4+2+1=7
若要rw-属性则4+2=6;
若要r-x属性则4+1=5。

使用实例

增加文件所有用户组可执行权限:

命令:

1
chmod a+x 2018511.log

输出:

1
2
3
4
5
6
[toor@localhost cmdtest]$ ls -al 2018511.log
-rw-rw-r--. 1 toor toor 0 5月 11 09:19 2018511.log
[toor@localhost cmdtest]$ chmod a+x 2018511.log
[toor@localhost cmdtest]$ ls -al 2018511.log
-rwxrwxr-x. 1 toor toor 0 5月 11 09:19 2018511.log
[toor@localhost cmdtest]$

说明:
即设定文件2018511.log的属性为:文件属主(u) 增加执行权限;与文件属主同组用户(g) 增加执行权限;其他用户(o) 增加执行权限。

同时修改不同用户权限:

命令:

1
chmod ug+w,o-x 2018511.log

输出:

1
2
3
4
5
6
[toor@localhost cmdtest]$ ls -al 2018511.log
-r-xr-xr-x. 1 toor toor 0 5月 11 09:19 2018511.log
[toor@localhost cmdtest]$ chmod ug+w,o-x 2018511.log
[toor@localhost cmdtest]$ ls -al 2018511.log
-rwxrwxr--. 1 toor toor 0 5月 11 09:19 2018511.log
[toor@localhost cmdtest]$

说明:
即设定文件text的属性为:文件属主(u) 增加写权限;与文件属主同组用户(g) 增加写权限;其他用户(o) 删除执行权限

删除文件权限:

命令:

1
chmod a-x 2018511.log

输出:

1
2
3
4
5
6
[toor@localhost cmdtest]$ ls -al 2018511.log
-rwxrwxr--. 1 toor toor 0 5月 11 09:19 2018511.log
[toor@localhost cmdtest]$ chmod a-x 2018511.log
[toor@localhost cmdtest]$ ls -al 2018511.log
-rw-rw-r--. 1 toor toor 0 5月 11 09:19 2018511.log
[toor@localhost cmdtest]$

说明:
删除所有用户的可执行权限

使用“=”设置权限

命令:

1
chmod u=x 2018511.log

输出:

1
2
3
4
5
6
[toor@localhost cmdtest]$ ls -al 2018511.log
-rw-rw-r--. 1 toor toor 0 5月 11 09:19 2018511.log
[toor@localhost cmdtest]$ chmod u=x 2018511.log
[toor@localhost cmdtest]$ ls -al 2018511.log
---xrw-r--. 1 toor toor 0 5月 11 09:19 2018511.log
[toor@localhost cmdtest]$

说明:
文件属主(u)等于执行权限;其它权限不变

对一个目录及其子目录所有文件添加权限:

命令:

1
chmod -R u+x test1

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[toor@localhost test1]$ ls -al
总用量 0
drwxrwxr-x. 2 toor toor 36 5月 11 10:46 .
drwxrwxr-x. 3 toor toor 36 5月 11 10:46 ..
-rw-rw-r--. 1 toor toor 0 5月 11 10:46 log1.log
-rw-rw-r--. 1 toor toor 0 5月 11 10:46 log2.log
[toor@localhost test1]$ cd ..
[toor@localhost cmdtest]$ chmod -R u+x test1
[toor@localhost cmdtest]$ cd test1
[toor@localhost test1]$ ls -al
总用量 0
drwxrwxr-x. 2 toor toor 36 5月 11 10:46 .
drwxrwxr-x. 3 toor toor 36 5月 11 10:46 ..
-rwxrw-r--. 1 toor toor 0 5月 11 10:46 log1.log
-rwxrw-r--. 1 toor toor 0 5月 11 10:46 log2.log
[toor@localhost test1]$

说明:
递归地给test1目录下所有文件和子目录的属主分配权限

其他实例:

给file的属主分配读、写、执行(7)的权限,给file的所在组分配读、执行(5)的权限,给其他用户分配执行(1)的权限,命令:

1
2
chmod 751 file
chmod u=rwx,g=rx,o=x file

为所有用户分配读权限,命令:

1
2
chmod 444 file
chmod a-wx,a+r file

参考:

http://www.cnblogs.com/peida/archive/2012/11/29/2794010.html

Linux ps命令

Linux中的ps命令是Process Status的缩写。ps命令用来列出系统中当前运行的那些进程。ps命令列出的是当前那些进程的快照,就是执行ps命令的那个时刻的那些进程,如果想要动态的显示进程信息,就可以使用top命令。

要对进程进行监测和控制,首先必须要了解当前进程的情况,也就是需要查看当前进程,而 ps 命令就是最基本同时也是非常强大的进程查看命令。使用该命令可以确定有哪些进程正在运行和运行的状态、进程是否结束、进程有没有僵死、哪些进程占用了过多的资源等等。总之大部分信息都是可以通过执行该命令得到的。

ps 为我们提供了进程的一次性的查看,它所提供的查看结果并不动态连续的;如果想对进程时间监控,应该用 top 工具。

kill 命令用于杀死进程。

linux上进程有5种状态

  1. 运行(正在运行或在运行队列中等待)
  2. 中断(休眠中, 受阻, 在等待某个条件的形成或接受到信号)
  3. 不可中断(收到信号不唤醒和不可运行, 进程必须等待直到有中断发生)
  4. 僵死(进程已终止, 但进程描述符存在, 直到父进程调用wait4()系统调用后释放)
  5. 停止(进程收到SIGSTOP, SIGSTP, SIGTIN, SIGTOU信号后停止运行运行)

ps工具标识进程的5种状态码

D 不可中断 uninterruptible sleep (usually IO)
R 运行 runnable (on run queue)
S 中断 sleeping
T 停止 traced or stopped
Z 僵死 a defunct (”zombie”) process

ps命令

** 命令格式:**
ps [参数]

** 命令功能:**
用来显示当前进程的状态

** 命令参数:**

a 显示所有进程
-a 显示同一终端下的所有程序
-A 显示所有进程
c 显示进程的真实名称
-N 反向选择
-e 等于“-A”
e 显示环境变量
f 显示程序间的关系
-H 显示树状结构
r 显示当前终端的进程
T 显示当前终端的所有程序
u 指定用户的所有进程
-au 显示较详细的资讯
-aux 显示所有包含其他使用者的行程
-C<命令> 列出指定命令的状况
–lines<行数> 每页显示的行数
–width<字符数> 每页显示的字符数
–help 显示帮助信息
–version 显示版本显示

** 使用实例 **

ps -A:显示所有进程信息

ps -u root:显示指定用户信息

ps -ef|grep ssh:ps 与grep 常用组合用法,查找特定进程

ps -l:将目前属于您自己这次登入的 PID 与相关信息列示出来

1
2
3
4
5
[root@localhost Desktop]# ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 2774 2722 0 80 0 - 47498 do_wai pts/0 00:00:00 su
4 S 0 2780 2774 0 80 0 - 29075 do_wai pts/0 00:00:00 bash
0 R 0 23118 2780 0 80 0 - 37235 - pts/0 00:00:00 ps

** 说明:**

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
F 代表这个程序的旗标 (flag), 4 代表使用者为 super user
S 代表这个程序的状态 (STAT),关于各 STAT 的意义将在内文介绍
UID 程序被该 UID 所拥有
PID 就是这个程序的 ID !
PPID 则是其上级父程序的ID
C CPU 使用的资源百分比
PRI 这个是 Priority (优先执行序) 的缩写,详细后面介绍
NI 这个是 Nice 值,在下一小节我们会持续介绍
ADDR 这个是 kernel function,指出该程序在内存的那个部分。如果是个 running的程序,一般就是 "-"
SZ 使用掉的内存大小
WCHAN 目前这个程序是否正在运作当中,若为 - 表示正在运作
TTY 登入者的终端机位置
TIME 使用掉的 CPU 时间。
CMD 所下达的指令为何
在预设的情况下, ps 仅会列出与目前所在的 bash shell 有关的 PID 而已,所以, 当我使用 ps -l 的时候,只有三个 PID。

ps -axjf:列出类似程序树的程序显示

ps aux | egrep '(cron|syslog)':找出与 cron 与 syslog 这两个服务有关的 PID 号码

ps -aux |more:用 | 管道和 more 连接起来分页查看

ps -aux > ps001.txt:把所有进程显示出来,并输出到ps001.txt文件

ps -o pid,ppid,pgrp,session,tpgid,comm:输出指定字段

ps -ef和ps aux的区别

Linux下显示系统进程的命令ps,最常用的有ps -ef 和ps aux。这两个到底有什么区别呢?两者没太大差别,讨论这个问题,要追溯到Unix系统中的两种风格,System V风格和BSD 风格,ps aux最初用到Unix Style中,而ps -ef被用在System V Style中,两者输出略有不同。现在的大部分Linux系统都是可以同时使用这两种方式的。

** ps -ef:显示所有进程信息,连同命令行 **

ps -ef 是用标准的格式显示进程的

1
2
3
4
5
6
7
8
9
10
[root@localhost Desktop]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 09:40 ? 00:00:03 /usr/lib/systemd/systemd --swi
root 2 0 0 09:40 ? 00:00:00 [kthreadd]
root 3 2 0 09:40 ? 00:00:00 [ksoftirqd/0]
root 5 2 0 09:40 ? 00:00:00 [kworker/0:0H]
root 7 2 0 09:40 ? 00:00:00 [migration/0]
root 8 2 0 09:40 ? 00:00:00 [rcu_bh]
root 9 2 0 09:40 ? 00:00:02 [rcu_sched]
root 10 2 0 09:40 ? 00:00:00 [watchdog/0]

参数详解:

1
2
3
4
5
6
7
UID    //用户ID、但输出的是用户名
PID //进程的ID
PPID //父进程ID
C //进程占用CPU的百分比
STIME //进程启动到现在的时间
TTY //该进程在那个终端上运行,若与终端无关,则显示? 若为pts/0等,则表示由网络连接主机进程。
CMD //命令的名称和参数

** ps aux:列出目前所有的正在内存当中的程序 **

ps aux 是用BSD的格式来显示

1
2
3
4
5
6
7
8
9
10
11
root@localhost Desktop]# ps -aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.4 193720 4236 ? Ss 09:40 0:03 /usr/lib/syste
root 2 0.0 0.0 0 0 ? S 09:40 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? S 09:40 0:00 [ksoftirqd/0]
root 5 0.0 0.0 0 0 ? S< 09:40 0:00 [kworker/0:0H]
root 7 0.0 0.0 0 0 ? S 09:40 0:00 [migration/0]
root 8 0.0 0.0 0 0 ? S 09:40 0:00 [rcu_bh]
root 9 0.0 0.0 0 0 ? R 09:40 0:02 [rcu_sched]
root 10 0.0 0.0 0 0 ? S 09:40 0:00 [watchdog/0]
root 12 0.0 0.0 0 0 ? S 09:40 0:00 [kdevtmpfs]

同ps -ef 不同的有列有

1
2
3
4
5
6
7
8
USER      //用户名
%CPU //进程占用的CPU百分比
%MEM //占用内存的百分比
VSZ //该进程使用的虚拟內存量(KB)
RSS //该进程占用的固定內存量(KB)(驻留中页的数量)
STAT //进程的状态
START //该进程被触发启动时间
TIME //该进程实际使用CPU运行的时间

其中STAT状态位常见的状态字符有

1
2
3
4
5
6
7
8
9
10
11
12
13
D      //无法中断的休眠状态(通常 IO 的进程);
R //正在运行可中在队列中可过行的;
S //处于休眠状态;
T //停止或被追踪;
W //进入内存交换 (从内核2.6开始无效);
X //死掉的进程 (基本很少见);
Z //僵尸进程;
< //优先级高的进程
N //优先级较低的进程
L //有些页被锁进内存;
s //进程的领导者(在它之下有子进程);
l //多线程,克隆线程(使用 CLONE_THREAD, 类似 NPTL pthreads);
+ //位于后台的进程组;

参考:

http://www.cnblogs.com/peida/archive/2012/12/19/2824418.html

https://www.linuxidc.com/Linux/2016-07/133515.htm

Linux grep命令

作用

Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来。grep全称是Global Regular Expression Print,表示全局正则表达式版本,它的使用权限是所有用户。

格式

grep [options]

主要参数

** [options]主要参数:**

-c:只输出匹配行的计数。
-I:不区分大 小写(只适用于单字符)。
-h:查询多文件时不显示文件名。
-l:查询多文件时只输出包含匹配字符的文件名。
-n:显示匹配行及 行号。
-s:不显示不存在或无匹配文本的错误信息。
-v:显示不包含匹配文本的所有行。

** pattern正则表达式主要参数:**

\: 忽略正则表达式中特殊字符的原有含义。
^:匹配正则表达式的开始行。
$: 匹配正则表达式的结束行。
<:从匹配正则表达 式的行开始。
\>:到匹配正则表达式的行结束。
[ ]:单个字符,如[A]即A符合要求 。
[ - ]:范围,如[A-Z],即A、B、C一直到Z都符合要求 。
。:所有的单个字符。
* :有字符,长度可以为0。

grep命令使用简单实例

ls |grep '1' t*
:显示所有以t开头的文件中包含‘1’的行

grep ‘test’ aa bb cc
:显示在aa,bb,cc文件中匹配test的行。

grep ‘[a-z]\{5\}’ aa
:显示所有包含每个字符串至少有5个连续小写字符的字符串的行。

grep命令使用复杂实例

假设您正在’/usr/src/Linux/Doc’目录下搜索带字符 串’magic’的文件:

1
2
3
$ grep magic /usr/src/Linux/Doc/*
sysrq.txt:* How do I enable the magic SysRQ key?
sysrq.txt:* How do I use the magic SysRQ key?

其中文件’sysrp.txt’包含该字符串,讨论的是 SysRQ 的功能。
默认情况下,’grep’只搜索当前目录。如果 此目录下有许多子目录,’grep’会以如下形式列出:
grep: sound: Is a directory
这可能会使’grep’ 的输出难于阅读。这里有两种解决的办法:

明确要求搜索子目录:grep -r
或忽略子目录:grep -d skip

如果有很多 输出时,您可以通过管道将其转到’less’上阅读:
$ grep magic /usr/src/Linux/Documentation/* | less
这样,您就可以更方便地阅读。

参考:

http://www.cnblogs.com/end/archive/2012/02/21/2360965.html

Linux shell中的竖线(|)——管道符号

在Linux系统中管道线是由竖杠(|)隔开的若干个命令组成的序列,在管道线中,每个命令运行时都有一个独立的进程。前一个命令的输出正是下一个命令的输入。而管道线中有一类命令也称作“过滤器”,过滤器首先读取输入,然后将输入以某种简单方式进行变换(相当于过滤),再将处理结果输出,例如grep、tail、sort和wc等命令就称为过滤器。

一个管道线中可以包括多条命令。

用法: command 1 | command 2

他的功能是把第一个命令command 1执行的结果作为command 2的输入传给command 2

例如:

1
ls -s|sort -nr

-s 是file size,-n是numeric-sort,-r是reverse,反转

该命令列出当前目录中的文档(含size),并把输出送给sort命令作为输入,sort命令按数字递减的顺序把ls的输出排序。

1
ls -s|sort -n

按从小到大的顺序输出。

参考:

http://blog.sina.com.cn/s/blog_6d09b5750100vley.html

https://blog.csdn.net/kaosini/article/details/6578115

三大核心概念:

镜像,容器,仓库

镜像是 Docker 的三大核心概念之一。Docker 运行容器前需要本地存在对应的镜像,如果本地没有对应的镜像,Docker 会尝试从默认的镜像仓库下载。当然用户也可以通过配置,使用自定义的镜像仓库。
本文将介绍镜像的具体操作,包括使用 pull 命令从 Docker Hub 的镜像仓库中拉取(下载)公共镜像;查看本地已有的镜像信息;使用 search 命令搜索镜像;删除镜像标签和镜像文件;创建用户自定义镜像并上传到 Docker Hub 镜像仓库。
与镜像相关的操作都被定义在 docker image 子命令中,虽然不带 image 的格式依然被兼容,但带上 image 后会让命令更容易理解,也会有更好的自动补全效果。

阅读全文 »

GitHub配置

SercretText

注:此处需要一个对项目有写权限的账户

进入SGithub –> Setting –> Developer settings –> Personal access tokens

1

2

3

自己先保存此token,如果丢失,之后再也无法找到这个token。

配置GitHub Plugin

系统管理 –> 系统设置 –> GitHub –> GitHub Plugin

配置github用户名,邮箱

4

配置Jenkins

新建任务

5

General(通常)

6

源码管理

7

点击Add:

8

构建触发器

H/2 * * * *

具体参考:

https://blog.csdn.net/brave_insist/article/details/78434877

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
每15分钟构建一次:H/15 * * * *   或*/5 * * * *

每天8点构建一次:0 8 * * *

每天8点~17点,两小时构建一次:0 8-17/2 * * *

周一到周五,8点~17点,两小时构建一次:0 8-17/2 * * 1-5

每月1号、15号各构建一次,除12月:H H 1,15 1-11 *

*/5 * * * * (每5分钟检查一次源码变化)

0 2 * * * (每天2:00 必须build一次源码)


每个部分代表的含义以及取值范围

分钟,取值范围(0~59):若其他值不做设定,则表示每个设定的分钟都会构建
如:5 * * * * ,表示每个小时的第5分钟都会构建一次

小时,取值范围(0~23):若其他值不做设定,则表示每个设定小时的每分钟都会构建
如:* 5 * * * ,表示在每天5点的时候,一小时内每一分钟都会构建一次

日期,取值范围(1~31):若其他值不做设定,则表示每个月的那一天每分钟都会构建一次
如:* * 5 * *,表示在每个月5号的时候,0点开始每分钟构建一次

月份,取值范围(1~12):若其他值不做设定,则表示每年的那个月每分钟都会构建一次
如:* * * 5 *,表示在每年的5月份,1号0点开始每分钟构建一次

星期,取值范围(0 ~ 7):若其他值不做设定,则表示每周的那一天几每分钟都会构建一次
如:* * * * 5,表示每周五0点开始每分钟构建一次

9

构建环境

10

点击Add:

10

11

构建

12

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/bash
# 获取短版本号

GITHASH=`git rev-parse --short HEAD`
echo ---------------Remove-Orphans------------------
docker-compose -f ./docker-compose.yml -f ./docker-compose.override.yml -p dotnetcoreapp1 down --rmi local --remove-orphans
echo ------------------Config-----------------------
docker-compose -f ./docker-compose.ci.build.yml -p dotnetcoreapp1 config
echo ------------------Build------------------------
docker-compose -f ./docker-compose.ci.build.yml -p dotnetcoreapp1 up --build
echo ---------------Publishing...------------------
docker-compose -f "./docker-compose.yml" -f "./docker-compose.override.yml" -p dotnetcoreapp1 up -d --build
echo ---------------Clear-Images...------------------
docker rmi -f $(docker images -f "dangling=true" -q)
echo ---------------Clear-Containers...------------------
docker rm dotnetcoreapp1_ci-build_1

命令说明:

1
2
3
-f, --file FILE 指定使用的 Compose 模板文件,默认为 docker-compose.yml,可以多次指定。

-p, --project-name NAME 指定项目名称,默认将使用所在目录名称作为项目名。

修改docker-compose.override.yml文件:

1
2
3
4
5
6
7
8
version: '3'

services:
dotnetcoreapp:
environment:
- ASPNETCORE_ENVIRONMENT=Development
ports:
- "8081:80"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
[MvcTest] $ /bin/bash /tmp/jenkins3923627102865574973.sh
---------------Remove-Orphans------------------

Removing network dotnetcoreapp1_default
------------------Config-----------------------

services:
ci-build:
command: /bin/bash -c "dotnet restore ./DotNetCoreApp.sln && dotnet publish ./DotNetCoreApp.sln
-c Release -o ./obj/Docker/publish"
image: microsoft/aspnetcore-build:1.0-2.0
volumes:
- /var/jenkins_home/workspace/MvcTest:/src:rw
working_dir: /src
version: '3.0'

------------------Build------------------------

Creating network "dotnetcoreapp1_default" with the default driver

Creating dotnetcoreapp1_ci-build_1 ...

[1A[2K
Creating dotnetcoreapp1_ci-build_1 ... [32mdone[0m
[1BAttaching to dotnetcoreapp1_ci-build_1
[36mci-build_1 |[0m Restoring packages for /src/DotNetCoreApp/DotNetCoreApp.csproj...

[36mci-build_1 |[0m Generating MSBuild file /src/DotNetCoreApp/obj/DotNetCoreApp.csproj.nuget.g.props.

[36mci-build_1 |[0m Generating MSBuild file /src/DotNetCoreApp/obj/DotNetCoreApp.csproj.nuget.g.targets.
[36mci-build_1 |[0m Restore completed in 30.06 sec for /src/DotNetCoreApp/DotNetCoreApp.csproj.
[36mci-build_1 |[0m Restoring packages for /src/DotNetCoreApp/DotNetCoreApp.csproj...

[36mci-build_1 |[0m Restore completed in 2.64 sec for /src/DotNetCoreApp/DotNetCoreApp.csproj.

[36mci-build_1 |[0m Microsoft (R) Build Engine version 15.6.84.34536 for .NET Core
[36mci-build_1 |[0m Copyright (C) Microsoft Corporation. All rights reserved.
[36mci-build_1 |[0m

[36mci-build_1 |[0m Restore completed in 97.25 ms for /src/DotNetCoreApp/DotNetCoreApp.csproj.
[36mci-build_1 |[0m Restore completed in 24.37 ms for /src/DotNetCoreApp/DotNetCoreApp.csproj.

[36mci-build_1 |[0m DotNetCoreApp -> /src/DotNetCoreApp/bin/Release/netcoreapp2.0/DotNetCoreApp.dll

[36mci-build_1 |[0m DotNetCoreApp -> /src/DotNetCoreApp/obj/Docker/publish/

[36mdotnetcoreapp1_ci-build_1 exited with code 0

[0m---------------Publishing...------------------

Building dotnetcoreapp

Step 1/6 : FROM microsoft/aspnetcore:2.0
---> c4ca78cf9dca
Step 2/6 : ARG source
---> Using cache
---> 5ccef217b449
Step 3/6 : WORKDIR /app
---> Using cache
---> 21ca58736a23
Step 4/6 : EXPOSE 80
---> Using cache
---> fa9898960c84
Step 5/6 : COPY ${source:-obj/Docker/publish} .

---> a7d0c6386eb4
Step 6/6 : ENTRYPOINT ["dotnet", "DotNetCoreApp.dll"]
---> Running in dd4cfb6f5cb8

Removing intermediate container dd4cfb6f5cb8
---> d8dea36554b4
Successfully built d8dea36554b4
Successfully tagged dotnetcoreapp:latest
Recreating dotnetcoreapp2_dotnetcoreapp_1 ...

[1A[2K
Recreating dotnetcoreapp2_dotnetcoreapp_1 ... [32mdone[0m
[1B---------------Clear-Images...------------------

Deleted: sha256:238c39ae8c13a1d6816361946429024cb46e6911329dad2d714033d2578da618
Deleted: sha256:12dfe61eae3ee68775237340f3e50e19554a653357baec0de52a50d0cff96652
Deleted: sha256:3f6beb8ffd03ee5d3b9fd0e9e5b46074d270cdb707fa07056087194a53be1dd4
---------------Clear-Containers...------------------

dotnetcoreapp1_ci-build_1
Finished: SUCCESS

最后通过浏览器访问http://localhost:8081

参考:

http://www.cnblogs.com/stulzq/p/8627824.html
https://github.com/muyinchen/woker/blob/master/%E9%9B%86%E6%88%90%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/%E6%89%8B%E6%8A%8A%E6%89%8B%E6%95%99%E4%BD%A0%E6%90%AD%E5%BB%BAJenkins%2BGithub%E6%8C%81%E7%BB%AD%E9%9B%86%E6%88%90%E7%8E%AF%E5%A2%83.md

http://www.cnblogs.com/LongJiangXie/p/7517909.html

http://www.cnblogs.com/JacZhu/p/6814848.html

卸载DotNetCore

查找dotnet命令:

1
which dotnet

查找dotnet相关的rpm包

1
rpm -qa|grep dotnet

移除相关包:

1
rpm -e dotnet-runtime-deps-2.1.0-preview2-26406-04-2.1.0_preview2_26406_04-1.x86_64