Last week I wrote about my self-hosted Sentry install in 3 Docker containers. This week I want to bring you the rest of my self-hosted tools for developers, all rolled into a convenient docker-compose.yml.

Contents

Version Control (GitLab)

Code Analysis (SonarQube)

Email (exim4)

Code Search (Etsy Hound)

Visualization (Grafana)

User Error Monitoring (Sentry)

System Monitoring (Prometheus)

Log Monitoring (ELK (Elasticsearch, Logstash, and Kibana))

Docker Web GUI (Portainer)

All Services Rolled Up

About The Configurations Shown

The configuration files described and shown below are exactly what I’m running at this time, 2018-04-05, (with personal details removed, of course) and therefore they may need to be adjusted slightly to your own preferences. Specifically, you will likely have to change the volumes for all the containers. I have them set to the /srv/$SERVICE_NAME and /srv/configs/$SERVICE_NAME paths for bulk data and configuration files respectively. The idea is that I would be able to move my docker-compose and configs directory to a new computer and immediately have this same stack up and running. Some bulk data may be lost, but I don’t consider any of it critical. The docker-compose file is using version 3.

Version Control (GitLab)

One of the most important developer tools is a version control system. Most developers use Git and especially GitHub. These are of course great tools, but I also run my own GitLab server. As the name suggests, GitLab uses the same Git system as always, but it has some more powerful features, chief among which is CI/CD. GitLab has a fairly simple continuous integration/continuous deployment system built in. It utilizes a .gitlab-ci.yml file placed in your repository to define operations to perform. It uses a separate docker container running GitLab Runner to spawn additional containers that execute the tasks you define in the gitlab-ci file. In addition to CI/CD, since you’re running your own server you can have as many private repositories as you want and even share private repositories with selected contributors.

Compose

The docker-compose section for my GitLab setup is shown below. Some things to note are that the GitLab Runner may need some additional setup, especially getting a registration token. Here are GitLab’s instructions for the registration process.

GitLab Stack
GitLab Stack

gitlab:

image: 'gitlab/gitlab-ce:latest'

restart: always

container_name: gitlab

hostname: # YOUR HOSTNAME ex. git.example.com

links:

- smtp

environment:

GITLAB_OMNIBUS_CONFIG: |

external_url '# YOUR URL ex. https://git.example.com #';

gitlab_rails['gitlab_email_from'] = '# YOUR EMAIL ADDRESS #';

gitlab_rails['gitlab_email_reply_to'] = '# YOUR EMAIL ADDRESS #';

gitlab_rails['smtp_enable'] = 'true';

gitlab_rails['smtp_address'] = 'smtp';

ports:

- '180:80'

volumes:

- '/srv/configs/gitlab/gitlab:/etc/gitlab'

- '/srv/gitlab/logs:/var/log/gitlab'

- '/srv/gitlab/data:/var/opt/gitlab'

End GitLab
GitLab CI/CD Runner

gitlab-runner:

image: 'gitlab/gitlab-runner:latest'

restart: always

container_name: gitlab-runner

links:

- gitlab

environment:

- CI_SERVER_URL=http://gitlab/

- RUNNER_NAME=local-docker-runner

- REGISTER_NON_INTERACTIVE=true

- REGISTRATION_TOKEN=# YOUR REGISTRATION TOKEN FROM GITLAB #

- RUNNER_EXECUTOR=docker

- DOCKER_IMAGE=ubuntu:artful

- REGISTER_LOCKED=false

volumes:

- /srv/configs/gitlab/gitlab-runner:/etc/gitlab-runner

- /srv/gitlab-runner/home:/home/gitlab-runner

- /var/run/docker.sock:/var/run/docker.sock

End GitLab CI/CD Runner
End GitLab Stack

Code Analysis (SonarQube)

Code just working isn’t good enough, you ought to enforce some guidelines on code style to avoid potential problems. One tool to do this is SonarQube, which is a static analysis tool. This means that it simply looks at your source code and will run a multitude of different rulesets against it looking for issues. It has support for all the popular languages and you can customize the rules that it enforces.

Compose

To use SonarQube you will need a MySQL or other supported server (the configuration below shows MySQL/MariaDB). You can run MySQL in another container or perhaps on a separate database server. Fill in the configuration below with the database information, and that should be all the setup required.

Sonarqube Static Code Analysis

sonarqube:

container_name: sonarqube

image: 'sonarqube:latest'

restart: always

links:

- smtp

ports:

- 780:9000

environment:

- SONARQUBE_JDBC_URL=jdbc:mysql://# MYSQL HOST #:3306/# MYSQL DATABASE #?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance

- SONARQUBE_JDBC_USERNAME=# MYSQL USERNAME #

- SONARQUBE_JDBC_PASSWORD=# MYSQL PASSWORD #

volumes:

- /srv/sonarqube/conf:/opt/sonarqube/conf

- /srv/sonarqube/data:/opt/sonarqube/data

- /srv/sonarqube/extensions:/opt/sonarqube/extensions

- /srv/sonarqube/bundled-plugins:/opt/sonarqube/lib/bundled-plugins/opt/sonarqube/lib/bundled-plugins

End Sonarqube Static Code Analysis

Email (exim4)

Many of the containers described in this article can take advantage of emails to alert you of issues if you set them up. A really simple way to do this if you don’t have your own mail server is to just use your existing GMail account.

Compose

SMTP Email

smtp:

image: 'tianon/exim4:latest'

restart: always

environment:

GMAIL_USER: # YOUR GMAIL USERNAME #

GMAIL_PASSWORD: # YOUR GMAIL PASSWORD #

End SMTP Email

Code Search (Etsy Hound)

Occasionally you may find that you’re writing something that you know you’ve done before, but you just can’t seem to find what project or file its in. Hound is a very simple code search tool that indexes your repositories and allows you to search them using regular expressions. Hound requires a bit of configuration in config.json which you can learn about here.

Compose

Hound Code Search

hound:

container_name: hound

image: 'etsy/hound:latest'

restart: always

ports:

- 580:6080

volumes:

- /srv/configs/hound/config.json:/data/config.json

- /srv/hound/data:/data/data

End Hound Code Search

Example Hound Configuration

Here is an example configuration for Hound, just put in your GitHub URLs and project names.

{

"max-concurrent-indexers" : 5,

"dbpath" : "data",

"repos" : {

"graphPlayground" : {

"url" : "https://github.com/MikeDombo/graphPlayground.git",

"enable-push-updates" : true

}

}

}

Visualization (Grafana)

If any of your projects are generating some statistics or writing into a database, then maybe you’d like a simple dashboard to visualize them. Grafana is the best way to do this without writing it yourself. It allows you to hookup many different datasources including MySQL, Graphite, Prometheus, and more and then show data in appealing graphs, tables, etc. Grafana comes with some dashboards and there are more community generated dashboards on their site. Most of the configuration you’ll do with Grafana is to setup a dashboard the way you like it.

Compose

Grafana Dashboard

grafana:

container_name: grafana

image: 'grafana/grafana:latest'

restart: always

links:

- smtp

ports:

- 680:3000

environment:

- GF_SERVER_ENABLE_GZIP=true

- GF_SERVER_ROOT_URL=%(protocol)s://%(domain)s/

- GF_SERVER_DOMAIN=# DOMAIN ex. graphs.example.com #

- GF_SMTP_ENABLED=true

- GF_SMTP_HOST=smtp

- GF_AUTH_ORG_NAME=anon_org

- GF_AUTH_ANONYMOUS_ENABLED=true

volumes:

- /srv/configs/grafana:/var/lib/grafana

End Grafana Dashboard

User Error Monitoring (Sentry)

See my post from last week to configure a self-hosted Sentry to collect errors that users encounter while using your applications.

System Monitoring (Prometheus)

Prometheus is one of several popular time-series databases. I use it to collect load, network, and other statistics from servers and Docker containers. I have it configured using Google CAdvisor and Prometheus’s node-exporter to gather stats on containers and hosts respectively. I then use Grafana to visualize the data from Prometheus.

Compose

Prometheus Monitoring Stack

prometheus:

container_name: prometheus

image: 'prom/prometheus:latest'

restart: always

links:

- grafana

- cadvisor

- node-exporter

command:

- '--config.file=/etc/prometheus/prometheus.yml'

- '--storage.tsdb.path=/prometheus'

- '--web.console.libraries=/usr/share/prometheus/console_libraries'

- '--web.console.templates=/usr/share/prometheus/consoles'

volumes:

- /srv/configs/prometheus:/etc/prometheus

- /srv/prometheus:/prometheus

Monitoring for this host

node-exporter:

image: prom/node-exporter

container_name: prometheus_node-exporter

volumes:

- /proc:/host/proc:ro

- /sys:/host/sys:ro

- /:/rootfs:ro

command:

- '--path.procfs=/host/proc'

- '--path.sysfs=/host/sys'

- --collector.filesystem.ignored-mount-points

- "^/(sys|proc|dev|host|etc|rootfs/var/lib/docker/containers|rootfs/var/lib/docker/overlay2|rootfs/run/docker/netns|rootfs/var/lib/docker/aufs)($|/)"

restart: always

Docker container monitoring

cadvisor:

image: google/cadvisor

restart: always

volumes:

- /:/rootfs:ro

- /var/run:/var/run:rw

- /sys:/sys:ro

- /var/lib/docker/:/var/lib/docker:ro

End Prometheus Monitoring Stack

Prometheus Configuration

Here as the Prometheus configuration that I used prometheus.yml to get node-exporter and cadvisor data into my Prometheus. Put it in /srv/configs/prometheus/prometheus.yml if you’re using my docker-compose file from above.

my global config

global:

scrape_interval: 15s # By default, scrape targets every 15 seconds.

evaluation_interval: 15s # By default, scrape targets every 15 seconds.

scrape_timeout is set to the global default (10s).

A scrape configuration containing exactly one endpoint to scrape:

Here it's Prometheus itself.

scrape_configs:

The job name is added as a label job=<job_name> to any timeseries scraped from this config.

  • job_name: 'prometheus'

    Override the global default and scrape targets from this job every 5 seconds.

    scrape_interval: 5s

    static_configs:

    • targets: ['localhost:9090']
  • job_name: 'node-exporter'

    Override the global default and scrape targets from this job every 5 seconds.

    scrape_interval: 5s

    static_configs:

    • targets: ['node-exporter:9100']
  • job_name: 'cadvisor'

    Override the global default and scrape targets from this job every 5 seconds.

    scrape_interval: 5s

    static_configs:

    • targets: ['cadvisor:8080']

      Log Monitoring (ELK (Elasticsearch, Logstash, and Kibana))

      To store and search through logs including Apache access and error logs and Linux system logs I use the ELK stack from Elastic.co.

      For configuration, you’ll have to setup Filebeat or some other way to get logs from your server and into ELK.

Compose

ELK Stack

elasticsearch:

image: docker.elastic.co/elasticsearch/elasticsearch-oss:6.3.0

container_name: elasticsearch

restart: always

volumes:

- /srv/configs/elk/elasticsearch/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro

- /srv/elk/elasticsearch/data:/usr/share/elasticsearch/data

ports:

- "9200:9200"

- "9300:9300"

environment:

ES_JAVA_OPTS: "-Xmx256m -Xms256m"

networks:

- elk

logstash:

image: docker.elastic.co/logstash/logstash-oss:6.3.0

container_name: logstash

restart: always

volumes:

- /srv/configs/elk/logstash/config:/usr/share/logstash/config:ro

- /srv/configs/elk/logstash/pipeline:/usr/share/logstash/pipeline:ro

ports:

- "5000:5000"

environment:

LS_JAVA_OPTS: "-Xmx256m -Xms256m"

networks:

- elk

depends_on:

- elasticsearch

kibana:

image: docker.elastic.co/kibana/kibana-oss:6.3.0

container_name: kibana

restart: always

volumes:

- /srv/configs/elk/kibana/:/usr/share/kibana/config:ro

ports:

- "5601:5601"

networks:

- elk

depends_on:

- elasticsearch

End ELK Stack

networks:

ELK Stack Network

elk:

driver: bridge

End ELK Stack Network

Configuration

I use the default ElasticSearch and Logstash configuration, and the following for Kibana. I also am including here a pipeline/logstash.conf which has rules for Apache access and error, PHP error, and Syslogs.

Kibana.yml

server.name: kibana

server.host: "0.0.0.0"

elasticsearch.url: http://elasticsearch:9200

pipeline/logstash.conf

input {

beats {

port => 5000

ssl => false

}

}

PHP

filter {

if "php_error" in [tags] {

grok {

match => { "message" => "^[(?%{MONTHDAY}-%{MONTH}-%{YEAR} %{TIME} (%{TZ}|(\w+/\w+)))] ?%{GREEDYDATA:message}" }

overwrite => [ "message" ]

}

date {
match => [ "logtime", "d-MMM-yyyy HH:mm:ss ZZZ" ]
remove_field => [ "logtime" ]
}

}

}

Apache Access and Error

filter {

if "apache_access" in [tags] {

grok {

match => [

"message" , "%{COMBINEDAPACHELOG}+%{GREEDYDATA:extra_fields}",

"message" , "%{COMMONAPACHELOG}+%{GREEDYDATA:extra_fields}"

]

overwrite => [ "message" ]

}

mutate {

convert => ["response", "integer"]

convert => ["bytes", "integer"]

convert => ["responsetime", "float"]

}

geoip {

source => "clientip"

target => "geoip"

add_tag => [ "apache-geoip" ]

}

date {

match => [ "timestamp" , "dd/MMM/YYYY:HH:mm:ss Z" ]

remove_field => [ "timestamp" ]

}

useragent {

source => "agent"

}

}

if "apache_error" in [tags] {

grok {

match => [ "message", "%{HTTPD_ERRORLOG}" ]

overwrite => ["message"]

}

if !("_grokparsefailure" in [tags]) {
geoip {
source => "clientip"
}
}

}

}

Syslog

filter {

if "syslog" in [tags] {

grok {

match => [ "message", "%{SYSLOGTIMESTAMP:syslog_timestamp} %{SYSLOGHOST:syslog_hostname} %{DATA:syslog_program}(?:[%{POSINT:syslog_pid}])?: %{GREEDYDATA:message}" ]

overwrite => ["message"]

}

date {

match => [ "syslog_timestamp", "MMM d HH:mm:ss", "MMM dd HH:mm:ss" ]

timezone => "America/New_York"

}

}

}

Removing annoying tag

filter {

if "beats_input_codec_plain_applied" in [tags] {

mutate {

remove_tag => ["beats_input_codec_plain_applied"]

}

}

}

Output

output {

elasticsearch {

hosts => "elasticsearch:9200"

sniffing => true

manage_template => false

document_type => "%{[@metadata][type]}"

}

}

Docker Web GUI (Portainer)

The simplest of all configurations, Portainer is a web app that enables you to manage your Docker containers.

Compose

Portainer Docker Web GUI

portainer:

container_name: portainer

image: 'portainer/portainer:latest'

restart: always

ports:

- '480:9000'

volumes:

- /var/run/docker.sock:/var/run/docker.sock

- /srv/configs/portainer:/data

End Portainer Docker Web GUI

All Rolled Up

For your convenience, here’s the whole docker-compose that I described in parts above. Many of the containers won’t run as-is, instead they’ll require a bit more configuration.

Compose
version: '3' services:
##### GitLab Stack #####
##### GitLab Stack #####
gitlab:
image: 'gitlab/gitlab-ce:latest'
restart: always
container_name: gitlab
hostname: # YOUR HOSTNAME ex. git.example.com
links:
- smtp
environment:
GITLAB_OMNIBUS_CONFIG: |
external_url '# YOUR URL ex. https://git.example.com #';
gitlab_rails['gitlab_email_from'] = '# YOUR EMAIL ADDRESS #';
gitlab_rails['gitlab_email_reply_to'] = '# YOUR EMAIL ADDRESS #';
gitlab_rails['smtp_enable'] = 'true';
gitlab_rails['smtp_address'] = 'smtp';
ports:
- '180:80'
volumes:
- '/srv/configs/gitlab/gitlab:/etc/gitlab'
- '/srv/gitlab/logs:/var/log/gitlab'
- '/srv/gitlab/data:/var/opt/gitlab'
##### End GitLab #####
##### GitLab CI/CD Runner #####
gitlab-runner:
image: 'gitlab/gitlab-runner:latest'
restart: always
container_name: gitlab-runner
links:
- gitlab
environment:
- CI_SERVER_URL=http://gitlab/
- RUNNER_NAME=local-docker-runner
- REGISTER_NON_INTERACTIVE=true
- REGISTRATION_TOKEN=# YOUR REGISTRATION TOKEN FROM GITLAB #
- RUNNER_EXECUTOR=docker
- DOCKER_IMAGE=ubuntu:artful
- REGISTER_LOCKED=false
volumes:
- /srv/configs/gitlab/gitlab-runner:/etc/gitlab-runner
- /srv/gitlab-runner/home:/home/gitlab-runner
- /var/run/docker.sock:/var/run/docker.sock
##### End GitLab CI/CD Runner #####
##### End GitLab Stack ##### ##### Sonarqube Static Code Analysis #####
sonarqube:
container_name: sonarqube
image: 'sonarqube:latest'
restart: always
links:
- smtp
ports:
- 780:9000
environment:
- SONARQUBE_JDBC_URL=jdbc:mysql://# MYSQL HOST #:3306/# MYSQL DATABASE #?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance
- SONARQUBE_JDBC_USERNAME=# MYSQL USERNAME #
- SONARQUBE_JDBC_PASSWORD=# MYSQL PASSWORD #
volumes:
- /srv/sonarqube/conf:/opt/sonarqube/conf
- /srv/sonarqube/data:/opt/sonarqube/data
- /srv/sonarqube/extensions:/opt/sonarqube/extensions
- /srv/sonarqube/bundled-plugins:/opt/sonarqube/lib/bundled-plugins/opt/sonarqube/lib/bundled-plugins
##### End Sonarqube Static Code Analysis ##### ##### SMTP Email #####
smtp:
image: 'tianon/exim4:latest'
restart: always
environment:
GMAIL_USER: # YOUR GMAIL USERNAME #
GMAIL_PASSWORD: # YOUR GMAIL PASSWORD #
##### End SMTP Email ##### ##### Hound Code Search #####
hound:
container_name: hound
image: 'etsy/hound:latest'
restart: always
ports:
- 580:6080
volumes:
- /srv/configs/hound/config.json:/data/config.json
- /srv/hound/data:/data/data
##### End Hound Code Search ##### ##### Grafana Dashboard #####
grafana:
container_name: grafana
image: 'grafana/grafana:latest'
restart: always
links:
- smtp
ports:
- 680:3000
environment:
- GF_SERVER_ENABLE_GZIP=true
- GF_SERVER_ROOT_URL=%(protocol)s://%(domain)s/
- GF_SERVER_DOMAIN=# DOMAIN ex. graphs.example.com #
- GF_SMTP_ENABLED=true
- GF_SMTP_HOST=smtp
- GF_AUTH_ORG_NAME=anon_org
- GF_AUTH_ANONYMOUS_ENABLED=true
volumes:
- /srv/configs/grafana:/var/lib/grafana
##### End Grafana Dashboard ##### ##### Sentry Stack #####
sentry-base:
image: 'sentry:latest'
container_name: sentry-base
restart: always
depends_on:
- sentry-redis
- sentry-postgres
links:
- sentry-redis
- sentry-postgres
ports:
- 880:9000
env_file:
- sentry.env
volumes:
- /srv/configs/sentry/sentry:/var/lib/sentry/files
sentry-cron:
image: 'sentry:latest'
container_name: sentry-cron
restart: always
depends_on:
- sentry-redis
- sentry-postgres
links:
- sentry-redis
- sentry-postgres
command: "sentry run cron"
env_file:
- sentry.env
volumes:
- /srv/configs/sentry/sentry:/var/lib/sentry/files
sentry-worker:
image: 'sentry:latest'
container_name: sentry-worker
restart: always
depends_on:
- sentry-redis
- sentry-postgres
links:
- sentry-redis
- sentry-postgres
command: "sentry run worker"
env_file:
- sentry.env
volumes:
- /srv/configs/sentry/sentry:/var/lib/sentry/files
sentry-redis:
image: 'redis:alpine'
container_name: sentry-redis
restart: always
sentry-postgres:
image: 'postgres:latest'
container_name: sentry-postgres
restart: always
environment:
POSTGRES_USER: sentry
POSTGRES_PASSWORD: sentry
POSTGRES_DB: sentry
volumes:
- /srv/configs/sentry/postgres:/var/lib/postgresql/data
##### End Sentry Stack ##### ##### Prometheus Monitoring Stack #####
prometheus:
container_name: prometheus
image: 'prom/prometheus:latest'
restart: always
links:
- grafana
- cadvisor
- node-exporter
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/usr/share/prometheus/console_libraries'
- '--web.console.templates=/usr/share/prometheus/consoles'
volumes:
- /srv/configs/prometheus:/etc/prometheus
- /srv/prometheus:/prometheus
# Monitoring for this host #
node-exporter:
image: prom/node-exporter
container_name: prometheus_node-exporter
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.sysfs=/host/sys'
- --collector.filesystem.ignored-mount-points
- "^/(sys|proc|dev|host|etc|rootfs/var/lib/docker/containers|rootfs/var/lib/docker/overlay2|rootfs/run/docker/netns|rootfs/var/lib/docker/aufs)($|/)"
restart: always
# Docker container monitoring #
cadvisor:
image: google/cadvisor
restart: always
volumes:
- /:/rootfs:ro
- /var/run:/var/run:rw
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
##### End Prometheus Monitoring Stack ##### ##### ELK Stack #####
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch-oss:6.3.0
container_name: elasticsearch
restart: always
volumes:
- /srv/configs/elk/elasticsearch/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro
- /srv/elk/elasticsearch/data:/usr/share/elasticsearch/data
ports:
- "9200:9200"
- "9300:9300"
environment:
ES_JAVA_OPTS: "-Xmx256m -Xms256m"
networks:
- elk
logstash:
image: docker.elastic.co/logstash/logstash-oss:6.3.0
container_name: logstash
restart: always
volumes:
- /srv/configs/elk/logstash/config:/usr/share/logstash/config:ro
- /srv/configs/elk/logstash/pipeline:/usr/share/logstash/pipeline:ro
ports:
- "5000:5000"
environment:
LS_JAVA_OPTS: "-Xmx256m -Xms256m"
networks:
- elk
depends_on:
- elasticsearch
kibana:
image: docker.elastic.co/kibana/kibana-oss:6.3.0
container_name: kibana
restart: always
volumes:
- /srv/configs/elk/kibana/:/usr/share/kibana/config:ro
ports:
- "5601:5601"
networks:
- elk
depends_on:
- elasticsearch
##### End ELK Stack ##### ##### Portainer Docker Web GUI #####
portainer:
container_name: portainer
image: 'portainer/portainer:latest'
restart: always
ports:
- '480:9000'
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /srv/configs/portainer:/data
##### End Portainer Docker Web GUI ##### networks:
##### ELK Stack Network #####
elk:
driver: bridge
##### End ELK Stack Network #####

from https://mikedombrowski.com/2018/04/docker-compose-setup-for-self-hosting-development-tools/

Docker-compose Setup for Self-hosting Development & Deployment Tools的更多相关文章

  1. Docker Compose 之进阶篇

    笔者在前文<Docker Compose 简介>和<Dcoker Compose 原理>两篇文章中分别介绍了 docker compose 的基本概念以及实现原理.本文我们将继 ...

  2. 使用docker compose编排容器

    一.安装docker compose 二进制包安装 1.安装 Docker Compose 从 官方 GitHub Release 处直接下载编译好的二进制文件即可 # curl -L https:/ ...

  3. kubernetes 实战6_命令_Share Process Namespace between Containers in a Pod&Translate a Docker Compose File to Kubernetes Resources

    Share Process Namespace between Containers in a Pod how to configure process namespace sharing for a ...

  4. [Docker] Converting from Docker Compose to Kubernetes

    kompose is a tool to help users who are familiar with docker-compose move to Kubernetes. kompose tak ...

  5. Docker Compose—简化复杂容器应用的利器

    Compose是用于定义和运行复杂Docker应用的工具.你可以在一个文件中定义一个多容器的应用,然后使用一条命令来启动你的应用,然后所有相关的操作都会被自动完成. 1. 安装Docker和Compo ...

  6. .NET遇上Docker - 使用Docker Compose组织Ngnix和.NETCore运行

    本文工具准备: Docker for Windows Visual Studio 2015 与 Visual Studio Tools for Docker 或 Visual Studio 2017 ...

  7. Docker学习笔记 - Docker Compose 脚本命令

    Docker Compose 配置文件包含 version.services.networks 三大部分,最关键的是 services 和 networks 两个部分, version: '2' se ...

  8. Docker入门(三)使用Docker Compose

    Compose介绍   Compose 项目是 Docker 官方的开源项目,负责实现对 Docker 容器集群的快速编排.Compose 是一个用户定义和运行多个容器的 Docker 应用程序.在 ...

  9. Docker Compose 原理

    Docker 的优势非常明显,尤其是对于开发者来说,它提供了一种全新的软件发布机制.也就是说使用 docker 镜像作为软件产品的载体,使用 docker 容器提供独立的软件运行上下文环境,使用 do ...

随机推荐

  1. eas之导入导出

    // 是否仅导出有数据的区域,该方法对所有的导出生效(默认为false)table.getIOManager().setExpandedOnly(true); 输入KDF 如果你已经有了一个完整的KD ...

  2. HDU1069 - Monkey and Banana【dp】

    题目大意 给定箱子种类数量n,及对应长宽高,每个箱子数量无限,求其能叠起来的最大高度是多少(上面箱子的长宽严格小于下面箱子) 思路 首先由于每种箱子有无穷个,而不仅可以横着放,还可以竖着放,歪着放.. ...

  3. 我的网站恢复访问了,http://FansUnion.cn

    博客网站 http://FansUnion.cn 恢复访问了. 周末,发表几篇原创文章.

  4. POJ 3762 The Bonus Salary!

    The Bonus Salary! Time Limit: 2000ms Memory Limit: 65536KB This problem will be judged on PKU. Origi ...

  5. mongodb--find基础用法

    聚集集合查询 1.查询所有记录 db.userInfo.find(); 相当于:select* from userInfo; 默认每页显示20条记录,当显示不下的情况下,可以用it迭代命令查询下一页数 ...

  6. 关于Hanoi算法

    java经典算法——河内算法(Hanoi) 有三根相邻的柱子,标号为A,B,C,A柱子上从下到上按金字塔状叠放着n个不同大小的圆盘,要把所有盘子一个一个移动到柱子B上,并且每次移动同一根柱子上都不能出 ...

  7. Git的基本设置

    进入虚拟机环境中:首先我们对 Git 进行用户名和邮箱进行设置,请参照下面格式,替换为你自己常用的用户名和邮箱来完成设置: $ git config --global user.name " ...

  8. Android 最新面试题

    1. Intent的几种有关Activity启动的方式有哪些,你了解每一个含义吗? Intent的一些标记有FLAG_ACTIVITY_BROUGHT_TO_FRONT .FLAG_ACTIVITY_ ...

  9. 51-nod -1284 2 3 5 7的倍数

    1284 . 2 3 5 7的倍数 基准时间限制:1 秒 空间限制:65536 KB 分值: 5 给出一个数N,求1至N中,有多少个数不是2 3 5 7的倍数. 比如N = 10,仅仅有1不是2 3 ...

  10. Java异常的捕获与处理

    Java提供了try(尝试).catch(捕捉).finally(最终)这三个关键字来处理异常.在处理各种异常时,需要用到对应的异常类,指的是由程序抛出的对象所属的类. 一.异常处理的使用 由于fin ...