mirror of
https://github.com/danbulant/docker-compose
synced 2026-06-14 12:11:25 +00:00
Compare commits
90 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
acb173b0dd | ||
|
|
18a9079ee6 | ||
|
|
748ba3e368 | ||
|
|
192979ffcc | ||
|
|
f60e4d5a18 | ||
|
|
dd4fe76eab | ||
|
|
6b9ab6150c | ||
|
|
a28e801590 | ||
|
|
b0ab29bbb3 | ||
|
|
d71e043be8 | ||
|
|
764f33fe1b | ||
|
|
9f84b89a45 | ||
|
|
d7fe723db3 | ||
|
|
74b4d6ea22 | ||
|
|
5921b51977 | ||
|
|
91abbfe63a | ||
|
|
639f9ceffd | ||
|
|
a3fb7c09bd | ||
|
|
26a3f0e9d8 | ||
|
|
866ac8d595 | ||
|
|
f7166c50c4 | ||
|
|
2fea41e6c1 | ||
|
|
1a7fec4601 | ||
|
|
c4b60872ae | ||
|
|
7eaf706be9 | ||
|
|
3b8aaec914 | ||
|
|
d9ed460405 | ||
|
|
0ebbc6f357 | ||
|
|
f5fb0b3907 | ||
|
|
5e969f588e | ||
|
|
e9bb9824a6 | ||
|
|
53fb97196f | ||
|
|
6dec0c6bb6 | ||
|
|
dbdb9008f2 | ||
|
|
8aa846553c | ||
|
|
21b63cbc53 | ||
|
|
48c9f0841a | ||
|
|
e7013dfab1 | ||
|
|
963b51573f | ||
|
|
361131a76b | ||
|
|
432413f087 | ||
|
|
44f0e9eeb3 | ||
|
|
58f09f4c74 | ||
|
|
876a032001 | ||
|
|
17aaf53a12 | ||
|
|
a3d0a52e36 | ||
|
|
e58387d82e | ||
|
|
524fe42a07 | ||
|
|
2de793b145 | ||
|
|
9c43efa2b2 | ||
|
|
c7c6f01658 | ||
|
|
2b089ff660 | ||
|
|
b487be048b | ||
|
|
57f00b36fe | ||
|
|
9443c7ebdc | ||
|
|
3be99e8360 | ||
|
|
880d2522b5 | ||
|
|
ed91eba770 | ||
|
|
51b20b43d6 | ||
|
|
6f105ca160 | ||
|
|
a2f5a4ec0e | ||
|
|
a7da0380a8 | ||
|
|
90421b7eb2 | ||
|
|
aa26e83884 | ||
|
|
70a98f473b | ||
|
|
b6eec0047d | ||
|
|
ecf4ba5e2b | ||
|
|
bfd45f47fa | ||
|
|
1bc50ed7a0 | ||
|
|
f83686e30e | ||
|
|
8d3c162015 | ||
|
|
bf8210ae9b | ||
|
|
46cb725156 | ||
|
|
bdbfc17de1 | ||
|
|
f85e6885dd | ||
|
|
ad6e008e1a | ||
|
|
a59476f65d | ||
|
|
d0bd17c8ec | ||
|
|
3495f93468 | ||
|
|
397000087c | ||
|
|
00f90c9620 | ||
|
|
c9abc11ffc | ||
|
|
afb2b1116b | ||
|
|
d2df827d0f | ||
|
|
af6d77b308 | ||
|
|
29cbab6298 | ||
|
|
ceb7ed6510 | ||
|
|
483e6827ad | ||
|
|
98c271de01 | ||
|
|
60e278d566 |
28 changed files with 6241 additions and 13204 deletions
|
|
@ -1,39 +0,0 @@
|
|||
# Javascript Node CircleCI 2.0 configuration file
|
||||
#
|
||||
# Check https://circleci.com/docs/2.0/language-javascript/ for more details
|
||||
#
|
||||
version: 2
|
||||
jobs:
|
||||
build:
|
||||
docker:
|
||||
# specify the version you desire here
|
||||
- image: circleci/node:10
|
||||
|
||||
# Specify service dependencies here if necessary
|
||||
# CircleCI maintains a library of pre-built images
|
||||
# documented at https://circleci.com/docs/2.0/circleci-images/
|
||||
# - image: circleci/mongo:3.4.4
|
||||
|
||||
working_directory: ~/repo
|
||||
|
||||
steps:
|
||||
- setup_remote_docker
|
||||
- checkout
|
||||
|
||||
# Download and cache dependencies
|
||||
- restore_cache:
|
||||
keys:
|
||||
- v1-dependencies-{{ checksum "package.json" }}
|
||||
# fallback to using the latest cache if no exact match is found
|
||||
- v1-dependencies-
|
||||
|
||||
- run: npm install
|
||||
|
||||
- save_cache:
|
||||
paths:
|
||||
- node_modules
|
||||
key: v1-dependencies-{{ checksum "package.json" }}
|
||||
|
||||
# run tests!
|
||||
- run: npm test
|
||||
|
||||
|
|
@ -3,11 +3,19 @@ root = true
|
|||
[**/**.yml]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
|
||||
[**/**.js]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
|
||||
[**/**.ts]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
|
||||
[**/**.json]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
|
|
|
|||
17
.eslintrc.js
Normal file
17
.eslintrc.js
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
module.exports = {
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:jest/recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:prettier/recommended'
|
||||
],
|
||||
env: {
|
||||
node: true,
|
||||
mocha: true,
|
||||
es6: true
|
||||
},
|
||||
plugins: ['@typescript-eslint', 'prettier'],
|
||||
parserOptions: {
|
||||
parser: '@typescript-eslint/parser'
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
{
|
||||
"extends": [
|
||||
"es/2015/server",
|
||||
"plugin:jest/recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
],
|
||||
"parserOptions": {
|
||||
"project": "./tsconfig.json"
|
||||
},
|
||||
"rules": {
|
||||
"no-console" :"off",
|
||||
"@typescript-eslint/indent": "off",
|
||||
"@typescript-eslint/interface-name-prefix": "off",
|
||||
"indent": [
|
||||
"warn",
|
||||
2,
|
||||
{
|
||||
"SwitchCase": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"plugins": [
|
||||
"jest",
|
||||
"@typescript-eslint"
|
||||
],
|
||||
"env": {
|
||||
"jest/globals": true
|
||||
}
|
||||
}
|
||||
31
.github/workflows/ci.yml
vendored
Normal file
31
.github/workflows/ci.yml
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
name: Node.js CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '*'
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-18.04
|
||||
name: Lint
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '12'
|
||||
- run: yarn
|
||||
- run: yarn lint
|
||||
build:
|
||||
runs-on: ubuntu-18.04
|
||||
name: Build + Test
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '12'
|
||||
- run: yarn
|
||||
- run: yarn build
|
||||
- run: yarn test
|
||||
56
.github/workflows/docs.yml
vendored
Normal file
56
.github/workflows/docs.yml
vendored
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
name: docs
|
||||
|
||||
on:
|
||||
# trigger deployment on every push to main branch
|
||||
push:
|
||||
branches: [master]
|
||||
# trigger deployment manually
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
docs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
# fetch all commits to get last updated time or other git log info
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
# choose node.js version to use
|
||||
node-version: '14'
|
||||
|
||||
# cache node_modules
|
||||
- name: Cache dependencies
|
||||
uses: actions/cache@v2
|
||||
id: yarn-cache
|
||||
with:
|
||||
path: |
|
||||
**/node_modules
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
|
||||
# install dependencies if the cache did not hit
|
||||
- name: Install dependencies
|
||||
if: steps.yarn-cache.outputs.cache-hit != 'true'
|
||||
run: yarn --frozen-lockfile
|
||||
|
||||
# run build script
|
||||
- name: Build VuePress site
|
||||
run: yarn docs:build
|
||||
|
||||
# please check out the docs of the workflow for more details
|
||||
# @see https://github.com/crazy-max/ghaction-github-pages
|
||||
- name: Deploy to GitHub Pages
|
||||
uses: crazy-max/ghaction-github-pages@v2
|
||||
with:
|
||||
# deploy to gh-pages branch
|
||||
target_branch: gh-pages
|
||||
# deploy the default output dir of VuePress
|
||||
build_dir: docs/.vuepress/dist
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -75,3 +75,7 @@ typings/
|
|||
# End of https://www.gitignore.io/api/node,jetbrains,visualstudiocode
|
||||
|
||||
/dist
|
||||
|
||||
### Vuepress ###
|
||||
.cache
|
||||
.temp
|
||||
1
.husky/.gitignore
vendored
Normal file
1
.husky/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
_
|
||||
22
.npmignore
22
.npmignore
|
|
@ -1,9 +1,17 @@
|
|||
# ignore all files in the test/ directory
|
||||
test/
|
||||
# ignore docs
|
||||
docs/
|
||||
community-samples/readme.md
|
||||
readme.md
|
||||
|
||||
# ignore ESLint and EditorConfig
|
||||
# ignore all files in the test/ directory and test settings
|
||||
test/
|
||||
jest.config.js
|
||||
|
||||
# ignore EditorConfig, ESLint, Prettier config
|
||||
.editorconfig
|
||||
.eslintrc.json
|
||||
.eslintrc.js
|
||||
.prettierrc.js
|
||||
|
||||
# JetBrains IDE settings
|
||||
.idea
|
||||
|
|
@ -11,5 +19,9 @@ test/
|
|||
# VS Code settings
|
||||
.vscode
|
||||
|
||||
# CircleCI
|
||||
.circleci
|
||||
# GitHub actions
|
||||
.github
|
||||
|
||||
# VuePress
|
||||
.cache
|
||||
.temp
|
||||
|
|
|
|||
12
.prettierrc.js
Normal file
12
.prettierrc.js
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
module.exports = {
|
||||
printWidth: 80,
|
||||
tabWidth: 2,
|
||||
singleQuote: true,
|
||||
quoteProps: 'as-needed',
|
||||
trailingComma: 'none',
|
||||
bracketSpacing: true,
|
||||
semi: false,
|
||||
useTabs: false,
|
||||
jsxBracketSameLine: false,
|
||||
proseWrap: 'never'
|
||||
}
|
||||
13
.vscode/settings.json
vendored
Normal file
13
.vscode/settings.json
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnPaste": true,
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
}
|
||||
}
|
||||
74
CHANGELOG.md
74
CHANGELOG.md
|
|
@ -2,6 +2,80 @@
|
|||
|
||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||
|
||||
### [0.23.14](https://github.com/PDMLab/docker-compose/compare/v0.23.13...v0.23.14) (2021-11-29)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* passing callback to report progress ([#191](https://github.com/PDMLab/docker-compose/issues/191)) ([f60e4d5](https://github.com/PDMLab/docker-compose/commit/f60e4d5a186ea3ca0b99e8443e1c4006d75be5a7))
|
||||
|
||||
### [0.23.13](https://github.com/PDMLab/docker-compose/compare/v0.23.12...v0.23.13) (2021-07-20)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* single container pause and unpause added ([5921b51](https://github.com/PDMLab/docker-compose/commit/5921b51977cbd51ffcb1def458738ccfccbe1dd9))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* now lints correctly ([74b4d6e](https://github.com/PDMLab/docker-compose/commit/74b4d6ea22d7e1b9ebbbbe9874e5314b7adfa31a))
|
||||
|
||||
### [0.23.12](https://github.com/PDMLab/docker-compose/compare/v0.23.11...v0.23.12) (2021-06-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **dx:** add default export ([c4b6087](https://github.com/PDMLab/docker-compose/commit/c4b60872aecfdc6610e9b2141a45ea7785820af7))
|
||||
|
||||
### [0.23.11](https://github.com/PDMLab/docker-compose/compare/v0.23.10...v0.23.11) (2021-06-04)
|
||||
|
||||
### [0.23.10](https://github.com/PDMLab/docker-compose/compare/v0.23.9...v0.23.10) (2021-05-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix mapping ipv6-based port mappings ([53fb971](https://github.com/PDMLab/docker-compose/commit/53fb97196f3cf0ebb229d127e9b630c863eaf8fc))
|
||||
* fix mapping ipv6-based port mappings ([6dec0c6](https://github.com/PDMLab/docker-compose/commit/6dec0c6bb6220b06eff188a26220b405d632bed3))
|
||||
* fix mapping ipv6-based port mappings ([dbdb900](https://github.com/PDMLab/docker-compose/commit/dbdb9008f25d237254312d79382e342d03f4c5bb))
|
||||
* fix mapping ipv6-based port mappings ([8aa8465](https://github.com/PDMLab/docker-compose/commit/8aa846553c2d045f610392bf38569fb3579b9aa6))
|
||||
* fix mapping ipv6-based port mappings ([21b63cb](https://github.com/PDMLab/docker-compose/commit/21b63cbc53635ee8532c388e57f4552f1b3ae6e3))
|
||||
* fix mapping ipv6-based port mappings ([48c9f08](https://github.com/PDMLab/docker-compose/commit/48c9f0841af2bbcb8ec666a38eee3ab8236304d0))
|
||||
* fix mapping ipv6-based port mappings ([e7013df](https://github.com/PDMLab/docker-compose/commit/e7013dfab10e4e369ee076b465c40a5bcb50802b))
|
||||
|
||||
### [0.23.9](https://github.com/PDMLab/docker-compose/compare/v0.23.8...v0.23.9) (2021-05-08)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add execPath option to set path to docker-compose executable ([58f09f4](https://github.com/PDMLab/docker-compose/commit/58f09f4c7414df5a6ee7af7f77d2af297d84d6c1))
|
||||
|
||||
### [0.23.8](https://github.com/PDMLab/docker-compose/compare/v0.23.7...v0.23.8) (2021-04-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* ignore vuepress cache + temp files on release ([#148](https://github.com/PDMLab/docker-compose/issues/148)) ([e58387d](https://github.com/PDMLab/docker-compose/commit/e58387d82e4586f7a8156446f12c999c9a6f9f42))
|
||||
|
||||
### [0.23.7](https://github.com/PDMLab/docker-compose/compare/v0.23.5...v0.23.7) (2021-04-14)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* allow to pass docker compose configuration as string ([e8c14d3](https://github.com/PDMLab/docker-compose/commit/e8c14d318ce440ab02c858b1ca1dbeeb2985dc00))
|
||||
* make result for `config --services` command type safe ([6f105ca](https://github.com/PDMLab/docker-compose/commit/6f105ca16098ba8de11f85ec0d092130b65293e4))
|
||||
* make result for `config --volumes` command type safe ([51b20b4](https://github.com/PDMLab/docker-compose/commit/51b20b43d6eccac45653553437a546e4ccee51a6))
|
||||
* make result for `config` command type safe ([a2f5a4e](https://github.com/PDMLab/docker-compose/commit/a2f5a4ec0eee8fcbd60fa12f969b8eb83a4730fb))
|
||||
* make result for `port` command type safe ([70a98f4](https://github.com/PDMLab/docker-compose/commit/70a98f473b7bd46f0aa03c1a4334fa2abf6c3455))
|
||||
* make result for `ps` command type safe ([880d252](https://github.com/PDMLab/docker-compose/commit/880d2522b5777db30c48569a41dd09fb7e46a4b3))
|
||||
* make result for `version` command type safe ([a7da038](https://github.com/PDMLab/docker-compose/commit/a7da0380a8464bbd2efc2c16b70b67d4fdf77c24))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* filter empty entries from `config --services` command ([ed91eba](https://github.com/PDMLab/docker-compose/commit/ed91eba770d3a32d82dda4e927d31ed4b6d01db4))
|
||||
* **test:** fix broken tests ([afb2b11](https://github.com/PDMLab/docker-compose/commit/afb2b1116b12c4800563e85adb15ebd39e030516))
|
||||
|
||||
### [0.23.6](https://github.com/PDMLab/docker-compose/compare/v0.23.5...v0.23.6) (2021-01-06)
|
||||
|
||||
|
||||
|
|
|
|||
2
LICENSE
2
LICENSE
|
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2017 - 2019 PDMLab
|
||||
Copyright (c) 2017 - 2021 PDMLab
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
|||
12
docs/.vuepress/config.js
Normal file
12
docs/.vuepress/config.js
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
module.exports = {
|
||||
base: '/docker-compose/',
|
||||
themeConfig: {
|
||||
navbar: [
|
||||
{ text: 'GitHub', link: 'https://github.com/PDMLab/docker-compose' },
|
||||
{ text: 'npm', link: 'https://npmjs.com/docker-compose' }
|
||||
],
|
||||
displayAllHeaders: true,
|
||||
lastUpdated: true,
|
||||
sidebar: []
|
||||
}
|
||||
}
|
||||
|
|
@ -1,20 +1,11 @@
|
|||
---
|
||||
layout: default
|
||||
title: README
|
||||
nav_order: 99
|
||||
title: Manage Docker-Compose via Node.js
|
||||
lang: en-US
|
||||
home: false
|
||||
---
|
||||
|
||||
<img src="https://img.shields.io/circleci/project/github/PDMLab/docker-compose.svg" /> <a href="https://join.slack.com/t/pdmlab-oss/shared_invite/enQtNjEyMjQ0MDY3NTczLTg1ZDc0YjQxMGE3MTcyYTdkODU1YjFmMTBiODE2ZTZiNDFkNjc1MWE4OTE4NWY0Y2YyMWYzYmNhZGY0NDAyYWY"><img src="https://img.shields.io/badge/Slack-join-green.svg?logo=slack" /></a>
|
||||
|
||||
# Manage Docker-Compose via Node.js
|
||||
|
||||
`docker-compose` is a small library that allows you to run [docker-compose](https://docs.docker.com/compose/)(which is still required) via Node.js. This is useful to bootstrap test environments. You might also generate your `docker-compose.yml` files using [composefile](https://www.npmjs.com/package/composefile).
|
||||
|
||||
## Existing user? We need your help
|
||||
First of all: thanks for using the `docker-compose` module.
|
||||
As described in [#44][i44], we're planning to provide more guidance for CI/CD when using the `docker-compose` module and it would be great if you could support us here. More details in [#44][i44].
|
||||
|
||||
[i44]: https://github.com/PDMLab/docker-compose/issues/44
|
||||
`docker-compose` is a small library that allows you to run [docker-compose](https://docs.docker.com/compose/) (which is still required) via Node.js. This is useful to bootstrap test environments.
|
||||
|
||||
## Installation
|
||||
|
||||
|
|
@ -26,26 +17,34 @@ npm install --save-dev docker-compose
|
|||
|
||||
`docker-compose` current supports these commands:
|
||||
|
||||
* `upAll(options)` - Builds, (re)creates, starts, and attaches to containers for all services - always uses the `-d` flag due to non interactive mode
|
||||
* `upMany(services, options)` - Builds, (re)creates, starts, and attaches to containers for the services specified in `services` - always uses the `-d` flag due to non interactive mode
|
||||
* `upOne(service, options)` - Builds, (re)creates, starts, and attaches to containers for a service specified in `service` - always uses the `-d` flag due to non interactive mode
|
||||
* `down(options)` - Stops containers and removes containers, networks, volumes, and images created by `up`
|
||||
* `kill(options)` - Force stop service containers
|
||||
* `stop(options)` - Stop running containers without removing them
|
||||
* `rm(options)` - Remove stopped service containers - always uses the `-f` flag due to non interactive mode
|
||||
* `exec(container, command, options)` - Exec `command` inside `container`, uses `-T` to properly handle stdin & stdout
|
||||
* `logs(container, command, options)` - Show logs of service. Use `options.follow` `true|false` to turn on `--follow` flag.
|
||||
* `run(service, command, options)` - Run a one-off `command` on a service, uses `-T` to properly handle stdin & stdout
|
||||
* `buildAll(options)` - Build or rebuild services
|
||||
* `buildMany(services, options)` - Build or rebuild services
|
||||
* `buildOne(service, options)` - Build or rebuild service
|
||||
* `restartAll(options)` - Restart all services
|
||||
* `restartMany(services, options)` - Restart services
|
||||
* `restartOne(service, options)` - Restart service
|
||||
* `ps(options)` - Lists containers information
|
||||
* `config(options)` - Validates configuration files and returns configuration yaml
|
||||
* `configServices(options)` - Returns list of services defined in configuration files
|
||||
* `configVolumes(options)` - Returns list of volumes defined in configuration files
|
||||
* `down(options)` - Stops containers and removes containers, networks, volumes, and images created by `up`
|
||||
* `exec(container, command, options)` - Exec `command` inside `container` - uses `-T` to properly handle stdin & stdout
|
||||
* `kill(options)` - Force stop service containers
|
||||
* `logs(services, options)` - Show logs of service(s) - use `options.follow` `true|false` to turn on `--follow` flag
|
||||
* `pauseOne(service, options)` - Pause the specified service
|
||||
* `port(service, containerPort, options)` - Returns the public port of the given service and internal port.
|
||||
* `ps(options)` - Lists containers information
|
||||
* `pullAll(options)` - Pull all service images
|
||||
* `pullMany(services, options)` - Pull service images specified
|
||||
* `pullOne(service, options)` - Pull a service image
|
||||
* `restartAll(options)` - Restart all services
|
||||
* `restartMany(services, options)` - Restart services
|
||||
* `restartOne(service, options)` - Restart service
|
||||
* `rm(options, services)` - Remove stopped service containers - always uses the `-f` flag due to non interactive mode - `services` can optionally be used to select the containers to remove
|
||||
* `run(service, command, options)` - Run a one-off `command` on a service - uses `-T` to properly handle stdin & stdout
|
||||
* `stop(options)` - Stop running containers without removing them
|
||||
* `stopOne(service, options)` - Stops one container without removing it
|
||||
* `unpauseOne(service, options)` - Resume the specified service
|
||||
* `upAll(options)` - Builds, (re)creates, starts, and attaches to containers for all services - always uses the `-d` flag due to non interactive mode
|
||||
* `upMany(services, options)` - Builds, (re)creates, starts, and attaches to containers for the services specified in `services` - always uses the `-d` flag due to non interactive mode
|
||||
* `upOne(service, options)` - Builds, (re)creates, starts, and attaches to containers for a service specified in `service` - always uses the `-d` flag due to non interactive mode
|
||||
* `version(options)` - Show `docker-compose` version strings
|
||||
|
||||
All commands return a `Promise({object})` with stdout and stderr strings and an exit code:
|
||||
```javascript
|
||||
|
|
@ -55,6 +54,7 @@ All commands return a `Promise({object})` with stdout and stderr strings and an
|
|||
exitCode: 0, // !== 0 in case of an error
|
||||
}
|
||||
```
|
||||
Although the return type is a `Promise`, it is still possible to get the process progres before the `Promise` resolves, by passing a callback function to the optional `callback` parameter.
|
||||
|
||||
### Example
|
||||
|
||||
|
|
@ -67,6 +67,19 @@ compose.upAll({ cwd: path.join(__dirname), log: true })
|
|||
err => { console.log('something went wrong:', err.message)}
|
||||
);
|
||||
```
|
||||
To get process progres
|
||||
```typescript
|
||||
compose.upAll({
|
||||
cwd: path.join(__dirname),
|
||||
callback: (chunk: Buffer) => {
|
||||
console.log('job in progres: ', chunk.ToString())
|
||||
}
|
||||
})
|
||||
.then(
|
||||
() => { console.log('job done')},
|
||||
err => { console.log('something went wrong:', err.message)}
|
||||
);
|
||||
```
|
||||
|
||||
To execute command inside a running container
|
||||
```javascript
|
||||
|
|
@ -78,9 +91,12 @@ compose.exec('node', 'npm install', { cwd: path.join(__dirname) })
|
|||
`docker-compose` accepts these params:
|
||||
|
||||
* `cwd {string}`: mandatory folder path to the `docker-compose.yml`
|
||||
* `executablePath {string}`: optional path to docker-compose executable in case it's not located in $PATH `/path/to/docker-compose`
|
||||
* `config {(string|string[])}`: custom and/or multiple yml files can be specified (relative to `cwd`)
|
||||
* `configAsString {string}`: configuration can be provided as is, instead of relying on a file. In case `configAsString` is provided `config` will be ignored.
|
||||
* `[log] {boolean}`: optional setting to enable console logging (output of `docker-compose` `stdout`/`stderr` output)
|
||||
* `[composeOptions] string[]|Array<string|string[]`: pass optional compose options like `"--verbose"` or `[["--verbose"], ["--log-level", "DEBUG"]]` or `["--verbose", ["--loglevel", "DEBUG"]]` for *all* commands.
|
||||
* `[callback] (chunk: Buffer, sourceStream?: 'stdout' | 'stderr') => void`: optional callback function, that provides infromation about the process while it is still runing.
|
||||
* `[commandOptions] string[]|Array<string|string[]`: pass optional command options like `"--build"` or `[["--build"], ["--timeout", "5"]]` or `["--build", ["--timeout", "5"]]` for the `up` command. Viable `commandOptions` depend on the command (`up`, `down` etc.) itself
|
||||
|
||||
## Running the tests
|
||||
|
|
@ -88,7 +104,7 @@ compose.exec('node', 'npm install', { cwd: path.join(__dirname) })
|
|||
While `docker-compose` runs on Node.js 6+, running the tests requires you to use Node.js 8 as they make use of `async/await`.
|
||||
|
||||
```
|
||||
npm test
|
||||
yarn test
|
||||
```
|
||||
|
||||
## Want to help?
|
||||
|
|
@ -101,17 +117,19 @@ If you see a bug, please be so kind as to show how it's failing, and we'll do ou
|
|||
|
||||
Before sending a PR, please [create an issue](https://github.com/PDMLab/docker-compose/issues/new) to introduce your idea and have a reference for your PR.
|
||||
|
||||
Also please add tests and make sure to run `npm run eslint`.
|
||||
We're using [conventional commits](https://www.conventionalcommits.org), so please use it for your commits as well.
|
||||
|
||||
### Slack
|
||||
Also please add tests and make sure to run `yarn lint`.
|
||||
|
||||
If you want to discuss an `docker-compose` issue or PR in more detail, feel free to [join our Slack workspace](https://join.slack.com/t/pdmlab-oss/shared_invite/enQtNjEyMjQ0MDY3NTczLTg1ZDc0YjQxMGE3MTcyYTdkODU1YjFmMTBiODE2ZTZiNDFkNjc1MWE4OTE4NWY0Y2YyMWYzYmNhZGY0NDAyYWY).
|
||||
### Discussions
|
||||
|
||||
If you want to discuss an `docker-compose` issue or PR in more detail, feel free to [start a discussion](https://github.com/PDMLab/docker-compose/discussions).
|
||||
|
||||
## License
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 - 2019 PDMLab
|
||||
Copyright (c) 2017 - 2021 PDMLab
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
title: docker-compose
|
||||
description: A Jekyll theme for documentation
|
||||
baseurl: "/docker-compose/" # the subpath of your site, e.g. /blog
|
||||
url: "https://pdmlab.github.io" # the base hostname & protocol for your site, e.g. http://example.com
|
||||
|
||||
permalink: pretty
|
||||
exclude: ["node_modules/", "*.gemspec", "*.gem", "Gemfile", "Gemfile.lock", "package.json", "package-lock.json", "script/", "LICENSE.txt", "lib/", "bin/", "README.md", "Rakefile"]
|
||||
|
||||
# Enable or disable the site search
|
||||
search_enabled: true
|
||||
|
||||
# Aux links for the upper right navigation
|
||||
aux_links:
|
||||
"docker-compose on GitHub":
|
||||
- "//github.com/pdmlab/docker-compose"
|
||||
|
||||
# Color scheme currently only supports "dark" or nil (default)
|
||||
color_scheme: nil
|
||||
|
||||
remote_theme: pmarsceill/just-the-docs
|
||||
|
||||
plugins:
|
||||
- jekyll-seo-tag
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
// //
|
||||
// // Typography
|
||||
// //
|
||||
//
|
||||
// $body-font-family: -apple-system, BlinkMacSystemFont, "helvetica neue", helvetica, roboto, noto, "segoe ui", arial, sans-serif;
|
||||
// $mono-font-family: "SFMono-Regular", Menlo, Consolas, Monospace;
|
||||
// $root-font-size: 16px; // Base font-size for rems
|
||||
// $body-line-height: 1.4;
|
||||
// $body-heading-line-height: 1.15;
|
||||
//
|
||||
// //
|
||||
// // Colors
|
||||
// //
|
||||
//
|
||||
// $white: #fff;
|
||||
//
|
||||
// $grey-dk-000: #959396;
|
||||
// $grey-dk-100: #5c5962;
|
||||
// $grey-dk-200: #44434d;
|
||||
// $grey-dk-250: #302d36 !default;
|
||||
// $grey-dk-300: #27262b;
|
||||
//
|
||||
// $grey-lt-000: #f5f6fa;
|
||||
// $grey-lt-100: #eeebee;
|
||||
// $grey-lt-200: #ecebed;
|
||||
// $grey-lt-300: #e6e1e8;
|
||||
//
|
||||
// $purple-000: #7253ed;
|
||||
// $purple-100: #5e41d0;
|
||||
// $purple-200: #4e26af;
|
||||
// $purple-300: #381885;
|
||||
//
|
||||
$blue-000: #2c84fa;
|
||||
// $blue-100: #2869e6;
|
||||
// $blue-200: #264caf;
|
||||
// $blue-300: #183385;
|
||||
//
|
||||
// $green-000: #41d693;
|
||||
// $green-100: #11b584;
|
||||
// $green-200: #009c7b;
|
||||
// $green-300: #026e57;
|
||||
//
|
||||
// $body-background-color: $white !default;
|
||||
// $sidebar-color: $grey-lt-000 !default;
|
||||
// $code-background-color: $grey-lt-000 !default;
|
||||
|
||||
// $body-text-color: $grey-dk-100 !default;
|
||||
// $body-heading-color: $grey-dk-300 !default;
|
||||
// $nav-child-link-color: $grey-dk-100 !default
|
||||
$link-color: $blue-000;
|
||||
// $btn-primary-color: $purple-100 !default;
|
||||
// $base-button-color: #f7f7f7 !default;
|
||||
//
|
||||
// //
|
||||
// // Media queries in pixels
|
||||
// //
|
||||
//
|
||||
// $media-queries: (
|
||||
// xs: 320px,
|
||||
// sm: 500px,
|
||||
// md: 740px,
|
||||
// lg: 1120px,
|
||||
// xl: 1400px
|
||||
// );
|
||||
//
|
||||
// //
|
||||
// // Spacing
|
||||
// //
|
||||
//
|
||||
// $spacing-unit: 1rem; // 1rem == 16px
|
||||
//
|
||||
// $spacers: (
|
||||
// sp-0: 0,
|
||||
// sp-1: $spacing-unit * 0.25,
|
||||
// sp-2: $spacing-unit * 0.5,
|
||||
// sp-3: $spacing-unit * 0.75,
|
||||
// sp-4: $spacing-unit,
|
||||
// sp-5: $spacing-unit * 1.5,
|
||||
// sp-6: $spacing-unit * 2,
|
||||
// sp-7: $spacing-unit * 2.5,
|
||||
// sp-8: $spacing-unit * 3,
|
||||
// sp-9: $spacing-unit * 3.5,
|
||||
// sp-10: $spacing-unit * 4
|
||||
// );
|
||||
//
|
||||
// $sp-1: map-get($spacers, sp-1); // 0.25 rem == 4px
|
||||
// $sp-2: map-get($spacers, sp-2); // 0.5 rem == 8px
|
||||
// $sp-3: map-get($spacers, sp-3); // 0.75 rem == 12px
|
||||
// $sp-4: map-get($spacers, sp-4); // 1 rem == 16px
|
||||
// $sp-5: map-get($spacers, sp-5); // 1.5 rem == 24px
|
||||
// $sp-6: map-get($spacers, sp-6); // 2 rem == 32px
|
||||
// $sp-7: map-get($spacers, sp-7); // 2.5 rem == 40px
|
||||
// $sp-8: map-get($spacers, sp-8); // 3 rem == 48px
|
||||
// $sp-9: map-get($spacers, sp-9); // 4 rem == 48px
|
||||
// $sp-10: map-get($spacers, sp-10); // 4.5 rem == 48px
|
||||
//
|
||||
// //
|
||||
// // Borders
|
||||
// //
|
||||
//
|
||||
// $border: 1px solid;
|
||||
// $border-radius: 4px;
|
||||
// $border-color: $grey-lt-100;
|
||||
//
|
||||
// //
|
||||
// // Grid system
|
||||
// //
|
||||
//
|
||||
// $gutter-spacing: $sp-6;
|
||||
// $gutter-spacing-sm: $sp-4;
|
||||
// $nav-width: 232px;
|
||||
// $content-width: 800px;
|
||||
//
|
||||
// $media-queries: (
|
||||
// xs: 320px,
|
||||
// sm: 500px,
|
||||
// md: 740px,
|
||||
// lg: 800px,
|
||||
// xl: 1316px
|
||||
// );
|
||||
10619
package-lock.json
generated
10619
package-lock.json
generated
File diff suppressed because it is too large
Load diff
58
package.json
58
package.json
|
|
@ -1,15 +1,17 @@
|
|||
{
|
||||
"name": "docker-compose",
|
||||
"version": "0.23.6",
|
||||
"name": "@iceprod/docker-compose",
|
||||
"version": "0.24.0",
|
||||
"main": "dist/index.js",
|
||||
"typings": "dist/index.d.ts",
|
||||
"types": "dist/index.d.ts",
|
||||
"scripts": {
|
||||
"test": "jest test --verbose",
|
||||
"eslint": "eslint src/**/*.ts test/**/*.ts",
|
||||
"lint": "eslint src/**/*.ts test/**/*.ts",
|
||||
"build": "tsc",
|
||||
"prepublishOnly": "tsc",
|
||||
"release": "yarn build && standard-version"
|
||||
"release": "yarn build && standard-version",
|
||||
"docs:dev": "vuepress dev docs",
|
||||
"docs:build": "vuepress build docs"
|
||||
},
|
||||
"repository": {
|
||||
"url": "git@github.com:PDMLab/docker-compose.git"
|
||||
|
|
@ -22,7 +24,7 @@
|
|||
"test",
|
||||
"test-tools"
|
||||
],
|
||||
"author": "Alexander Zeitler <alexander.zeitler@pdmlab.com>",
|
||||
"author": "Alexander Zeitler <alexander.zeitler@pdmlab.com>, Daniel Bulan <danbulant@danbulant.eu>",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Ignatiev Mikhail"
|
||||
|
|
@ -70,28 +72,39 @@
|
|||
{
|
||||
"name": "Gabriel Fürstenheim",
|
||||
"url": "https://github.com/furstenheim"
|
||||
},
|
||||
{
|
||||
"name": "gautaz"
|
||||
},
|
||||
{
|
||||
"name": "Daniel Bulant",
|
||||
"url": "https://github.com/danbulant"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"description": "Manage docker-compose from Node.js",
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^8.2.0",
|
||||
"@commitlint/config-conventional": "^8.2.0",
|
||||
"@commitlint/cli": "^13.1.0",
|
||||
"@commitlint/config-conventional": "13.1.0",
|
||||
"@types/dockerode": "^2.5.27",
|
||||
"@types/jest": "^25.1.4",
|
||||
"@types/node": "^10.17.17",
|
||||
"@typescript-eslint/eslint-plugin": "^2.23.0",
|
||||
"@typescript-eslint/parser": "^2.23.0",
|
||||
"dockerode": "^3.1.0",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-config-es": "^3.19.44",
|
||||
"eslint-plugin-extended": "^0.2.0",
|
||||
"eslint-plugin-jest": "^23.8.2",
|
||||
"husky": "^4.2.3",
|
||||
"jest": "^25.1.0",
|
||||
"standard-version": "^8.0.1",
|
||||
"ts-jest": "^25.2.1",
|
||||
"typescript": "^3.8.3"
|
||||
"@types/jest": "^26.0.22",
|
||||
"@types/node": "^12.12.6",
|
||||
"@typescript-eslint/eslint-plugin": "^4.21.0",
|
||||
"@typescript-eslint/parser": "^4.21.0",
|
||||
"dockerode": "^3.2.1",
|
||||
"eslint": "^7.24.0",
|
||||
"eslint-config-prettier": "^8.1.0",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-jest": "^24.3.4",
|
||||
"eslint-plugin-prettier": "^3.3.1",
|
||||
"eslint-watch": "^7.0.0",
|
||||
"husky": "^6.0.0",
|
||||
"jest": "^26.6.3",
|
||||
"prettier": "^2.2.1",
|
||||
"standard-version": "9.3.1",
|
||||
"ts-jest": "^26.5.4",
|
||||
"typescript": "^4.2.4",
|
||||
"vuepress": "^2.0.0-beta.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6.0.0"
|
||||
|
|
@ -105,5 +118,8 @@
|
|||
"extends": [
|
||||
"@commitlint/config-conventional"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"yaml": "^1.10.2"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
106
readme.md
106
readme.md
|
|
@ -1,87 +1,46 @@
|
|||
[](https://conventionalcommits.org) [](https://gitter.im/pdmlab/docker-compose?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) <img src="https://img.shields.io/circleci/project/github/PDMLab/docker-compose.svg" /> <a href="https://join.slack.com/t/pdmlab-oss/shared_invite/enQtNjEyMjQ0MDY3NTczLTg1ZDc0YjQxMGE3MTcyYTdkODU1YjFmMTBiODE2ZTZiNDFkNjc1MWE4OTE4NWY0Y2YyMWYzYmNhZGY0NDAyYWY"><img src="https://img.shields.io/npm/dm/docker-compose.svg" /> <img src="https://img.shields.io/badge/Slack-join-green.svg?logo=slack" /></a>
|
||||
[](https://conventionalcommits.org) [](https://gitter.im/pdmlab/docker-compose?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) <img src="https://img.shields.io/github/workflow/status/pdmlab/docker-compose/Node.js%20CI/master" /> <img src="https://img.shields.io/npm/dm/docker-compose.svg" />
|
||||
|
||||
# Manage Docker-Compose via Node.js
|
||||
|
||||
`docker-compose` is a small library that allows you to run [docker-compose](https://docs.docker.com/compose/)(which is still required) via Node.js. This is useful to bootstrap test environments. You might also generate your `docker-compose.yml` files using [composefile](https://www.npmjs.com/package/composefile).
|
||||
`docker-compose` is a small library that allows you to run [docker-compose](https://docs.docker.com/compose/)(which is still required) via Node.js. This is useful to bootstrap test environments.
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
npm install --save-dev docker-compose
|
||||
```bash
|
||||
yarn add --dev docker-compose
|
||||
```
|
||||
|
||||
## Usage
|
||||
## Documentation
|
||||
|
||||
`docker-compose` current supports these commands:
|
||||
The documentation can be found [here](https://pdmlab.github.io/docker-compose/).
|
||||
|
||||
* `upAll(options)` - Builds, (re)creates, starts, and attaches to containers for all services - always uses the `-d` flag due to non interactive mode
|
||||
* `upMany(services, options)` - Builds, (re)creates, starts, and attaches to containers for the services specified in `services` - always uses the `-d` flag due to non interactive mode
|
||||
* `upOne(service, options)` - Builds, (re)creates, starts, and attaches to containers for a service specified in `service` - always uses the `-d` flag due to non interactive mode
|
||||
* `down(options)` - Stops containers and removes containers, networks, volumes, and images created by `up`
|
||||
* `kill(options)` - Force stop service containers
|
||||
* `stop(options)` - Stop running containers without removing them
|
||||
* `stopOne(service, options)` - Stops one container without removing it
|
||||
* `rm(options)` - Remove stopped service containers - always uses the `-f` flag due to non interactive mode
|
||||
* `exec(container, command, options)` - Exec `command` inside `container`, uses `-T` to properly handle stdin & stdout
|
||||
* `logs(services, options)` - Show logs of service(s). Use `options.follow` `true|false` to turn on `--follow` flag.
|
||||
* `run(service, command, options)` - Run a one-off `command` on a service, uses `-T` to properly handle stdin & stdout
|
||||
* `buildAll(options)` - Build or rebuild services
|
||||
* `buildMany(services, options)` - Build or rebuild services
|
||||
* `buildOne(service, options)` - Build or rebuild service
|
||||
* `pullMany(services, options)` - Pull service images specified
|
||||
* `pullOne(service, options)` - Pull a service image
|
||||
* `pullAll(options)` - Pull all service images
|
||||
* `restartAll(options)` - Restart all services
|
||||
* `restartMany(services, options)` - Restart services
|
||||
* `restartOne(service, options)` - Restart service
|
||||
* `ps(options)` - Lists containers information
|
||||
* `config(options)` - Validates configuration files and returns configuration yaml
|
||||
* `configServices(options)` - Returns list of services defined in configuration files
|
||||
* `configVolumes(options)` - Returns list of volumes defined in configuration files
|
||||
|
||||
All commands return a `Promise({object})` with stdout and stderr strings and an exit code:
|
||||
```javascript
|
||||
{
|
||||
out: 'stdout contents',
|
||||
err: 'stderr contents',
|
||||
exitCode: 0, // !== 0 in case of an error
|
||||
}
|
||||
```
|
||||
|
||||
### Example
|
||||
## Example
|
||||
|
||||
To start service containers based on the `docker-compose.yml` file in your current directory, just call `compose.up` like this:
|
||||
|
||||
```javascript
|
||||
compose.upAll({ cwd: path.join(__dirname), log: true })
|
||||
.then(
|
||||
() => { console.log('done')},
|
||||
err => { console.log('something went wrong:', err.message)}
|
||||
);
|
||||
compose.upAll({ cwd: path.join(__dirname), log: true }).then(
|
||||
() => {
|
||||
console.log('done')
|
||||
},
|
||||
(err) => {
|
||||
console.log('something went wrong:', err.message)
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
To execute command inside a running container
|
||||
|
||||
```javascript
|
||||
compose.exec('node', 'npm install', { cwd: path.join(__dirname) })
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
`docker-compose` accepts these params:
|
||||
|
||||
* `cwd {string}`: mandatory folder path to the `docker-compose.yml`
|
||||
* `config {(string|string[])}`: custom and/or multiple yml files can be specified (relative to `cwd`)
|
||||
* `configAsString {string}`: configuration can be provided as is, instead of relying on a file. In case `configAsString` is provided `config` will be ignored.
|
||||
* `[log] {boolean}`: optional setting to enable console logging (output of `docker-compose` `stdout`/`stderr` output)
|
||||
* `[composeOptions] string[]|Array<string|string[]`: pass optional compose options like `"--verbose"` or `[["--verbose"], ["--log-level", "DEBUG"]]` or `["--verbose", ["--loglevel", "DEBUG"]]` for *all* commands.
|
||||
* `[commandOptions] string[]|Array<string|string[]`: pass optional command options like `"--build"` or `[["--build"], ["--timeout", "5"]]` or `["--build", ["--timeout", "5"]]` for the `up` command. Viable `commandOptions` depend on the command (`up`, `down` etc.) itself
|
||||
|
||||
## Running the tests
|
||||
|
||||
While `docker-compose` runs on Node.js 6+, running the tests requires you to use Node.js 8 as they make use of `async/await`.
|
||||
While `docker-compose` runs on Node.js 6+, running the tests requires you to use Node.js 8+ as they make use of `async/await`.
|
||||
|
||||
```
|
||||
npm test
|
||||
```bash
|
||||
yarn test
|
||||
```
|
||||
|
||||
## Want to help?
|
||||
|
|
@ -96,33 +55,20 @@ Before sending a PR, please [create an issue](https://github.com/PDMLab/docker-c
|
|||
|
||||
We're using [conventional commits](https://www.conventionalcommits.org), so please use it for your commits as well.
|
||||
|
||||
Also please add tests and make sure to run `npm run eslint`.
|
||||
Also please add tests and make sure to run `yarn lint`.
|
||||
|
||||
### Slack
|
||||
### Discussions
|
||||
|
||||
If you want to discuss an `docker-compose` issue or PR in more detail, feel free to [join our Slack workspace](https://join.slack.com/t/pdmlab-oss/shared_invite/enQtNjEyMjQ0MDY3NTczLTg1ZDc0YjQxMGE3MTcyYTdkODU1YjFmMTBiODE2ZTZiNDFkNjc1MWE4OTE4NWY0Y2YyMWYzYmNhZGY0NDAyYWY).
|
||||
If you want to discuss an `docker-compose` issue or PR in more detail, feel free to [start a discussion](https://github.com/PDMLab/docker-compose/discussions).
|
||||
|
||||
## License
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 - 2019 PDMLab
|
||||
Copyright (c) 2017 - 2021 PDMLab
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
|
|
|||
622
src/index.ts
622
src/index.ts
|
|
@ -1,31 +1,106 @@
|
|||
import childProcess from 'child_process';
|
||||
import { Readable } from 'stream'
|
||||
import childProcess from 'child_process'
|
||||
import yaml from 'yaml'
|
||||
import mapPorts from './map-ports'
|
||||
|
||||
export interface IDockerComposeOptions {
|
||||
cwd?: string;
|
||||
config?: string | string[];
|
||||
configAsString?: string;
|
||||
log?: boolean;
|
||||
composeOptions?: string[] | (string | string[])[];
|
||||
commandOptions?: string[] | (string | string[])[];
|
||||
env?: NodeJS.ProcessEnv;
|
||||
cwd?: string
|
||||
executablePath?: string
|
||||
config?: string | string[]
|
||||
configAsString?: string
|
||||
log?: boolean
|
||||
composeOptions?: string[] | (string | string[])[]
|
||||
commandOptions?: string[] | (string | string[])[]
|
||||
env?: NodeJS.ProcessEnv
|
||||
callback?: (chunk: Buffer, streamSource?: 'stdout' | 'stderr') => void
|
||||
}
|
||||
|
||||
export type DockerComposePortResult = {
|
||||
address: string
|
||||
port: number
|
||||
}
|
||||
|
||||
export type DockerComposeVersionResult = {
|
||||
version: string
|
||||
}
|
||||
|
||||
export type DockerComposeConfigResult = {
|
||||
config: {
|
||||
version: Record<string, string>
|
||||
services: Record<string, string | Record<string, string>>
|
||||
volumes: Record<string, string>
|
||||
}
|
||||
}
|
||||
|
||||
export type DockerComposeConfigServicesResult = {
|
||||
services: string[]
|
||||
}
|
||||
|
||||
export type DockerComposeConfigVolumesResult = {
|
||||
volumes: string[]
|
||||
}
|
||||
|
||||
export interface IDockerComposeLogOptions extends IDockerComposeOptions {
|
||||
follow?: boolean;
|
||||
follow?: boolean
|
||||
}
|
||||
|
||||
export interface IDockerComposeBuildOptions extends IDockerComposeOptions {
|
||||
parallel?: boolean;
|
||||
parallel?: boolean
|
||||
}
|
||||
|
||||
export interface IDockerComposePushOptions extends IDockerComposeOptions {
|
||||
ignorePushFailures?: boolean;
|
||||
ignorePushFailures?: boolean
|
||||
}
|
||||
|
||||
export interface IDockerComposeResult {
|
||||
exitCode: number | null;
|
||||
out: string;
|
||||
err: string;
|
||||
exitCode: number | null
|
||||
out: string
|
||||
err: string
|
||||
}
|
||||
|
||||
export type TypedDockerComposeResult<T> = {
|
||||
exitCode: number | null
|
||||
out: string
|
||||
err: string
|
||||
data: T
|
||||
}
|
||||
|
||||
const nonEmptyString = (v: string) => v !== ''
|
||||
|
||||
export type DockerComposePsResult = {
|
||||
services: Array<{
|
||||
name: string
|
||||
command: string
|
||||
state: string
|
||||
ports: Array<{
|
||||
mapped?: { address: string; port: number }
|
||||
exposed: { port: number; protocol: string }
|
||||
}>
|
||||
}>
|
||||
}
|
||||
|
||||
export const mapPsOutput = (output: string): DockerComposePsResult => {
|
||||
const services = output
|
||||
.split(`\n`)
|
||||
.filter(nonEmptyString)
|
||||
.filter((_, index) => index > 0)
|
||||
.map((line) => {
|
||||
const [
|
||||
nameFragment,
|
||||
commandFragment,
|
||||
serviceFragment,
|
||||
stateFragment,
|
||||
untypedPortsFragment
|
||||
] = line.split(/\s{3,}/)
|
||||
|
||||
return {
|
||||
name: nameFragment.trim(),
|
||||
command: commandFragment.trim(),
|
||||
service: serviceFragment.trim(),
|
||||
state: stateFragment.trim(),
|
||||
ports: mapPorts(untypedPortsFragment.trim())
|
||||
}
|
||||
})
|
||||
return { services }
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -34,231 +109,434 @@ export interface IDockerComposeResult {
|
|||
*/
|
||||
const configToArgs = (config): string[] => {
|
||||
if (typeof config === 'undefined') {
|
||||
return [];
|
||||
return []
|
||||
} else if (typeof config === 'string') {
|
||||
return [ '-f', config ];
|
||||
return ['-f', config]
|
||||
} else if (config instanceof Array) {
|
||||
return config.reduce((args, item): string[] => args.concat([ '-f', item ]), []);
|
||||
return config.reduce(
|
||||
(args, item): string[] => args.concat(['-f', item]),
|
||||
[]
|
||||
)
|
||||
}
|
||||
throw new Error(`Invalid argument supplied: ${config}`);
|
||||
};
|
||||
throw new Error(`Invalid argument supplied: ${config}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts docker-compose commandline options to cli arguments
|
||||
*/
|
||||
const composeOptionsToArgs = (composeOptions): string[] => {
|
||||
let composeArgs: string[] = [];
|
||||
let composeArgs: string[] = []
|
||||
|
||||
composeOptions.forEach((option: string[] | string): void => {
|
||||
if (option instanceof Array) {
|
||||
composeArgs = composeArgs.concat(option);
|
||||
composeArgs = composeArgs.concat(option)
|
||||
}
|
||||
if (typeof option === 'string') {
|
||||
composeArgs = composeArgs.concat([ option ]);
|
||||
composeArgs = composeArgs.concat([option])
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
return composeArgs;
|
||||
};
|
||||
return composeArgs
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes docker-compose command with common options
|
||||
*/
|
||||
const execCompose = (command, args, options: IDockerComposeOptions = {}): Promise<IDockerComposeResult> => new Promise((resolve, reject): void => {
|
||||
const composeOptions = options.composeOptions || [];
|
||||
const commandOptions = options.commandOptions || [];
|
||||
let composeArgs = composeOptionsToArgs(composeOptions);
|
||||
const isConfigProvidedAsString = !!options.configAsString;
|
||||
export const execCompose = (
|
||||
command,
|
||||
args,
|
||||
options: IDockerComposeOptions = {}
|
||||
): Promise<IDockerComposeResult> =>
|
||||
new Promise((resolve, reject): void => {
|
||||
const composeOptions = options.composeOptions || []
|
||||
const commandOptions = options.commandOptions || []
|
||||
let composeArgs = composeOptionsToArgs(composeOptions)
|
||||
const isConfigProvidedAsString = !!options.configAsString
|
||||
|
||||
const configArgs = isConfigProvidedAsString ? [ '-f', '-' ] : configToArgs(options.config);
|
||||
const configArgs = isConfigProvidedAsString
|
||||
? ['-f', '-']
|
||||
: configToArgs(options.config)
|
||||
|
||||
composeArgs = composeArgs.concat(configArgs.concat([ command ].concat(composeOptionsToArgs(commandOptions), args)));
|
||||
composeArgs = composeArgs.concat(
|
||||
configArgs.concat(
|
||||
[command].concat(composeOptionsToArgs(commandOptions), args)
|
||||
)
|
||||
)
|
||||
|
||||
const cwd = options.cwd;
|
||||
const env = options.env || undefined;
|
||||
const cwd = options.cwd
|
||||
const env = options.env || undefined
|
||||
const executablePath = options.executablePath || 'docker-compose'
|
||||
|
||||
const childProc = childProcess.spawn('docker-compose', composeArgs, { cwd, env });
|
||||
const childProc = childProcess.spawn(executablePath, composeArgs, {
|
||||
cwd,
|
||||
env
|
||||
})
|
||||
|
||||
childProc.on('error', (err): void => {
|
||||
reject(err);
|
||||
});
|
||||
childProc.on('error', (err): void => {
|
||||
reject(err)
|
||||
})
|
||||
|
||||
const result: IDockerComposeResult = {
|
||||
exitCode: null,
|
||||
err: '',
|
||||
out: ''
|
||||
};
|
||||
|
||||
childProc.stdout.on('data', (chunk): void => {
|
||||
result.out += chunk.toString();
|
||||
});
|
||||
|
||||
childProc.stderr.on('data', (chunk): void => {
|
||||
result.err += chunk.toString();
|
||||
});
|
||||
|
||||
childProc.on('exit', (exitCode): void => {
|
||||
result.exitCode = exitCode;
|
||||
if (exitCode === 0) {
|
||||
resolve(result);
|
||||
} else {
|
||||
reject(result);
|
||||
const result: IDockerComposeResult = {
|
||||
exitCode: null,
|
||||
err: '',
|
||||
out: ''
|
||||
}
|
||||
});
|
||||
|
||||
if (isConfigProvidedAsString) {
|
||||
childProc.stdin.write(options.configAsString);
|
||||
childProc.stdin.end();
|
||||
}
|
||||
childProc.stdout.on('data', (chunk): void => {
|
||||
result.out += chunk.toString()
|
||||
options.callback?.(chunk, 'stdout')
|
||||
})
|
||||
|
||||
if (options.log) {
|
||||
childProc.stdout.pipe(process.stdout);
|
||||
childProc.stderr.pipe(process.stderr);
|
||||
}
|
||||
});
|
||||
childProc.stderr.on('data', (chunk): void => {
|
||||
result.err += chunk.toString()
|
||||
options.callback?.(chunk, 'stderr')
|
||||
})
|
||||
|
||||
childProc.on('exit', (exitCode): void => {
|
||||
result.exitCode = exitCode
|
||||
if (exitCode === 0) {
|
||||
resolve(result)
|
||||
} else {
|
||||
reject(result)
|
||||
}
|
||||
})
|
||||
|
||||
if (isConfigProvidedAsString) {
|
||||
childProc.stdin.write(options.configAsString)
|
||||
childProc.stdin.end()
|
||||
}
|
||||
|
||||
if (options.log) {
|
||||
childProc.stdout.pipe(process.stdout)
|
||||
childProc.stderr.pipe(process.stderr)
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* Determines whether or not to use the default non-interactive flag -d for up commands
|
||||
*/
|
||||
const shouldUseDefaultNonInteractiveFlag = function(options: IDockerComposeOptions = {}): boolean {
|
||||
const commandOptions = options.commandOptions || [];
|
||||
const containsOtherNonInteractiveFlag = commandOptions.reduce((memo: boolean, item: string | string[]) => {
|
||||
return memo && !item.includes('--abort-on-container-exit') && !item.includes('--no-start');
|
||||
}, true);
|
||||
return containsOtherNonInteractiveFlag;
|
||||
};
|
||||
const shouldUseDefaultNonInteractiveFlag = function (
|
||||
options: IDockerComposeOptions = {}
|
||||
): boolean {
|
||||
const commandOptions = options.commandOptions || []
|
||||
const containsOtherNonInteractiveFlag = commandOptions.reduce(
|
||||
(memo: boolean, item: string | string[]) => {
|
||||
return (
|
||||
memo &&
|
||||
!item.includes('--abort-on-container-exit') &&
|
||||
!item.includes('--no-start')
|
||||
)
|
||||
},
|
||||
true
|
||||
)
|
||||
return containsOtherNonInteractiveFlag
|
||||
}
|
||||
|
||||
export const upAll = function (options?: IDockerComposeOptions): Promise<IDockerComposeResult> {
|
||||
const args = shouldUseDefaultNonInteractiveFlag(options) ? [ '-d' ] : [];
|
||||
return execCompose('up', args, options);
|
||||
};
|
||||
export const upAll = function (
|
||||
options?: IDockerComposeOptions
|
||||
): Promise<IDockerComposeResult> {
|
||||
const args = shouldUseDefaultNonInteractiveFlag(options) ? ['-d'] : []
|
||||
return execCompose('up', args, options)
|
||||
}
|
||||
|
||||
export const upMany = function (services: string[], options?: IDockerComposeOptions): Promise<IDockerComposeResult> {
|
||||
const args = shouldUseDefaultNonInteractiveFlag(options) ? [ '-d' ].concat(services) : services;
|
||||
return execCompose('up', args, options);
|
||||
};
|
||||
export const upMany = function (
|
||||
services: string[],
|
||||
options?: IDockerComposeOptions
|
||||
): Promise<IDockerComposeResult> {
|
||||
const args = shouldUseDefaultNonInteractiveFlag(options)
|
||||
? ['-d'].concat(services)
|
||||
: services
|
||||
return execCompose('up', args, options)
|
||||
}
|
||||
|
||||
export const upOne = function (service: string, options?: IDockerComposeOptions): Promise<IDockerComposeResult> {
|
||||
const args = shouldUseDefaultNonInteractiveFlag(options) ? [ '-d', service ] : [ service ];
|
||||
return execCompose('up', args, options);
|
||||
};
|
||||
export const upOne = function (
|
||||
service: string,
|
||||
options?: IDockerComposeOptions
|
||||
): Promise<IDockerComposeResult> {
|
||||
const args = shouldUseDefaultNonInteractiveFlag(options)
|
||||
? ['-d', service]
|
||||
: [service]
|
||||
return execCompose('up', args, options)
|
||||
}
|
||||
|
||||
export const down = function (options?: IDockerComposeOptions): Promise<IDockerComposeResult> {
|
||||
return execCompose('down', [], options);
|
||||
};
|
||||
export const down = function (
|
||||
options?: IDockerComposeOptions
|
||||
): Promise<IDockerComposeResult> {
|
||||
return execCompose('down', [], options)
|
||||
}
|
||||
|
||||
export const stop = function (options?: IDockerComposeOptions): Promise<IDockerComposeResult> {
|
||||
return execCompose('stop', [], options);
|
||||
};
|
||||
export const stop = function (
|
||||
options?: IDockerComposeOptions
|
||||
): Promise<IDockerComposeResult> {
|
||||
return execCompose('stop', [], options)
|
||||
}
|
||||
|
||||
export const stopOne = function (service: string, options?: IDockerComposeOptions): Promise<IDockerComposeResult> {
|
||||
return execCompose('stop', [ service ], options);
|
||||
};
|
||||
export const stopOne = function (
|
||||
service: string,
|
||||
options?: IDockerComposeOptions
|
||||
): Promise<IDockerComposeResult> {
|
||||
return execCompose('stop', [service], options)
|
||||
}
|
||||
|
||||
export const kill = function (options?: IDockerComposeOptions): Promise<IDockerComposeResult> {
|
||||
return execCompose('kill', [], options);
|
||||
};
|
||||
export const pauseOne = function (
|
||||
service: string,
|
||||
options?: IDockerComposeOptions
|
||||
): Promise<IDockerComposeResult> {
|
||||
return execCompose('pause', [service], options)
|
||||
}
|
||||
|
||||
export const rm = function (options?: IDockerComposeOptions, ...services: string[]): Promise<IDockerComposeResult> {
|
||||
return execCompose('rm', [ '-f', ...services ], options);
|
||||
};
|
||||
export const unpauseOne = function (
|
||||
service: string,
|
||||
options?: IDockerComposeOptions
|
||||
): Promise<IDockerComposeResult> {
|
||||
return execCompose('unpause', [service], options)
|
||||
}
|
||||
|
||||
export const exec = function (container: string, command: string | string[], options?: IDockerComposeOptions): Promise<IDockerComposeResult> {
|
||||
const args = Array.isArray(command) ? command : command.split(/\s+/);
|
||||
export const kill = function (
|
||||
options?: IDockerComposeOptions
|
||||
): Promise<IDockerComposeResult> {
|
||||
return execCompose('kill', [], options)
|
||||
}
|
||||
|
||||
return execCompose('exec', [ '-T', container ].concat(args), options);
|
||||
};
|
||||
export const rm = function (
|
||||
options?: IDockerComposeOptions,
|
||||
...services: string[]
|
||||
): Promise<IDockerComposeResult> {
|
||||
return execCompose('rm', ['-f', ...services], options)
|
||||
}
|
||||
|
||||
export const run = function (container: string, command: string | string[], options?: IDockerComposeOptions): Promise<IDockerComposeResult> {
|
||||
const args = Array.isArray(command) ? command : command.split(/\s+/);
|
||||
export const exec = function (
|
||||
container: string,
|
||||
command: string | string[],
|
||||
options?: IDockerComposeOptions
|
||||
): Promise<IDockerComposeResult> {
|
||||
const args = Array.isArray(command) ? command : command.split(/\s+/)
|
||||
|
||||
return execCompose('run', [ '-T', container ].concat(args), options);
|
||||
};
|
||||
return execCompose('exec', ['-T', container].concat(args), options)
|
||||
}
|
||||
|
||||
export const buildAll = function (options: IDockerComposeBuildOptions = {}): Promise<IDockerComposeResult> {
|
||||
export const run = function (
|
||||
container: string,
|
||||
command: string | string[],
|
||||
options?: IDockerComposeOptions
|
||||
): Promise<IDockerComposeResult> {
|
||||
const args = Array.isArray(command) ? command : command.split(/\s+/)
|
||||
|
||||
return execCompose('run', ['-T', container].concat(args), options)
|
||||
}
|
||||
|
||||
export const buildAll = function (
|
||||
options: IDockerComposeBuildOptions = {}
|
||||
): Promise<IDockerComposeResult> {
|
||||
return execCompose('build', options.parallel ? ['--parallel'] : [], options)
|
||||
}
|
||||
|
||||
export const buildMany = function (
|
||||
services: string[],
|
||||
options: IDockerComposeBuildOptions = {}
|
||||
): Promise<IDockerComposeResult> {
|
||||
return execCompose(
|
||||
'build',
|
||||
options.parallel ? [ '--parallel' ] : [],
|
||||
options.parallel ? ['--parallel'].concat(services) : services,
|
||||
options
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export const buildMany = function (services: string[], options: IDockerComposeBuildOptions = {}): Promise<IDockerComposeResult> {
|
||||
return execCompose(
|
||||
'build',
|
||||
options.parallel ? [ '--parallel' ].concat(services) : services,
|
||||
options
|
||||
);
|
||||
};
|
||||
export const buildOne = function (
|
||||
service: string,
|
||||
options?: IDockerComposeBuildOptions
|
||||
): Promise<IDockerComposeResult> {
|
||||
return execCompose('build', [service], options)
|
||||
}
|
||||
|
||||
export const buildOne = function (service: string, options?: IDockerComposeBuildOptions): Promise<IDockerComposeResult> {
|
||||
return execCompose('build', [ service ], options);
|
||||
};
|
||||
export const pullAll = function (
|
||||
options: IDockerComposeOptions = {}
|
||||
): Promise<IDockerComposeResult> {
|
||||
return execCompose('pull', [], options)
|
||||
}
|
||||
|
||||
export const pullAll = function (options: IDockerComposeOptions = {}): Promise<IDockerComposeResult> {
|
||||
return execCompose('pull', [], options);
|
||||
};
|
||||
export const pullMany = function (
|
||||
services: string[],
|
||||
options: IDockerComposeOptions = {}
|
||||
): Promise<IDockerComposeResult> {
|
||||
return execCompose('pull', services, options)
|
||||
}
|
||||
|
||||
export const pullMany = function (services: string[], options: IDockerComposeOptions = {}): Promise<IDockerComposeResult> {
|
||||
return execCompose('pull', services, options);
|
||||
};
|
||||
export const pullOne = function (
|
||||
service: string,
|
||||
options?: IDockerComposeOptions
|
||||
): Promise<IDockerComposeResult> {
|
||||
return execCompose('pull', [service], options)
|
||||
}
|
||||
|
||||
export const pullOne = function (service: string, options?: IDockerComposeOptions): Promise<IDockerComposeResult> {
|
||||
return execCompose('pull', [ service ], options);
|
||||
};
|
||||
export const config = async function (
|
||||
options?: IDockerComposeOptions
|
||||
): Promise<TypedDockerComposeResult<DockerComposeConfigResult>> {
|
||||
try {
|
||||
const result = await execCompose('config', [], options)
|
||||
const config = yaml.parse(result.out)
|
||||
return {
|
||||
...result,
|
||||
data: { config }
|
||||
}
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
export const config = function (options?: IDockerComposeOptions): Promise<IDockerComposeResult> {
|
||||
return execCompose('config', [], options);
|
||||
};
|
||||
export const configServices = async function (
|
||||
options?: IDockerComposeOptions
|
||||
): Promise<TypedDockerComposeResult<DockerComposeConfigServicesResult>> {
|
||||
try {
|
||||
const result = await execCompose('config', ['--services'], options)
|
||||
const services = result.out.split('\n').filter(nonEmptyString)
|
||||
return {
|
||||
...result,
|
||||
data: { services }
|
||||
}
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
export const configServices = function (options?: IDockerComposeOptions): Promise<IDockerComposeResult> {
|
||||
return execCompose('config', [ '--services' ], options);
|
||||
};
|
||||
export const configVolumes = async function (
|
||||
options?: IDockerComposeOptions
|
||||
): Promise<TypedDockerComposeResult<DockerComposeConfigVolumesResult>> {
|
||||
try {
|
||||
const result = await execCompose('config', ['--volumes'], options)
|
||||
const volumes = result.out.split('\n').filter(nonEmptyString)
|
||||
return {
|
||||
...result,
|
||||
data: { volumes }
|
||||
}
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
export const configVolumes = function (options?: IDockerComposeOptions): Promise<IDockerComposeResult> {
|
||||
return execCompose('config', [ '--volumes' ], options);
|
||||
};
|
||||
export const ps = async function (
|
||||
options?: IDockerComposeOptions
|
||||
): Promise<TypedDockerComposeResult<DockerComposePsResult>> {
|
||||
try {
|
||||
const result = await execCompose('ps', [], options)
|
||||
const data = mapPsOutput(result.out)
|
||||
return {
|
||||
...result,
|
||||
data
|
||||
}
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
export const ps = function (options?: IDockerComposeOptions): Promise<IDockerComposeResult> {
|
||||
return execCompose('ps', [], options);
|
||||
};
|
||||
|
||||
export const push = function (options: IDockerComposePushOptions = {}): Promise<IDockerComposeResult> {
|
||||
export const push = function (
|
||||
options: IDockerComposePushOptions = {}
|
||||
): Promise<IDockerComposeResult> {
|
||||
return execCompose(
|
||||
'push',
|
||||
options.ignorePushFailures ? [ '--ignore-push-failures' ] : [],
|
||||
options.ignorePushFailures ? ['--ignore-push-failures'] : [],
|
||||
options
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export const restartAll = function (options?: IDockerComposeOptions): Promise<IDockerComposeResult> {
|
||||
return execCompose('restart', [], options);
|
||||
};
|
||||
export const restartAll = function (
|
||||
options?: IDockerComposeOptions
|
||||
): Promise<IDockerComposeResult> {
|
||||
return execCompose('restart', [], options)
|
||||
}
|
||||
|
||||
export const restartMany = function (services: string[], options?: IDockerComposeOptions): Promise<IDockerComposeResult> {
|
||||
return execCompose('restart', services, options);
|
||||
};
|
||||
export const restartMany = function (
|
||||
services: string[],
|
||||
options?: IDockerComposeOptions
|
||||
): Promise<IDockerComposeResult> {
|
||||
return execCompose('restart', services, options)
|
||||
}
|
||||
|
||||
export const restartOne = function (service: string, options?: IDockerComposeOptions): Promise<IDockerComposeResult> {
|
||||
return restartMany([ service ], options);
|
||||
};
|
||||
export const restartOne = function (
|
||||
service: string,
|
||||
options?: IDockerComposeOptions
|
||||
): Promise<IDockerComposeResult> {
|
||||
return restartMany([service], options)
|
||||
}
|
||||
|
||||
export const logs = function (services: string | string[], options: IDockerComposeLogOptions = {}): Promise<IDockerComposeResult> {
|
||||
let args = Array.isArray(services) ? services : [ services ];
|
||||
export const logs = function (
|
||||
services: string | string[],
|
||||
options: IDockerComposeLogOptions = {}
|
||||
): Promise<IDockerComposeResult> {
|
||||
let args = Array.isArray(services) ? services : [services]
|
||||
|
||||
if (options.follow) {
|
||||
args = [ '--follow', ...args ];
|
||||
args = ['--follow', ...args]
|
||||
}
|
||||
|
||||
return execCompose('logs', args, options);
|
||||
};
|
||||
return execCompose('logs', args, options)
|
||||
}
|
||||
|
||||
export const port = function (service: string, containerPort: string | number, options?: IDockerComposeOptions): Promise<IDockerComposeResult> {
|
||||
const args = [ service, containerPort ];
|
||||
export const port = async function (
|
||||
service: string,
|
||||
containerPort: string | number,
|
||||
options?: IDockerComposeOptions
|
||||
): Promise<TypedDockerComposeResult<DockerComposePortResult>> {
|
||||
const args = [service, containerPort]
|
||||
|
||||
return execCompose('port', args, options);
|
||||
};
|
||||
try {
|
||||
const result = await execCompose('port', args, options)
|
||||
const [address, port] = result.out.split(':')
|
||||
return {
|
||||
...result,
|
||||
data: {
|
||||
address,
|
||||
port: Number(port)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
export const version = function (options?: IDockerComposeOptions): Promise<IDockerComposeResult> {
|
||||
return execCompose('version', [ '--short' ], options);
|
||||
};
|
||||
export const version = async function (
|
||||
options?: IDockerComposeOptions
|
||||
): Promise<TypedDockerComposeResult<DockerComposeVersionResult>> {
|
||||
try {
|
||||
const result = await execCompose('version', ['--short'], options)
|
||||
const version = result.out.replace('\n', '')
|
||||
return {
|
||||
...result,
|
||||
data: { version }
|
||||
}
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
upAll,
|
||||
upMany,
|
||||
upOne,
|
||||
down,
|
||||
stop,
|
||||
stopOne,
|
||||
pauseOne,
|
||||
unpauseOne,
|
||||
kill,
|
||||
rm,
|
||||
exec,
|
||||
run,
|
||||
buildAll,
|
||||
buildMany,
|
||||
buildOne,
|
||||
pullAll,
|
||||
pullMany,
|
||||
pullOne,
|
||||
config,
|
||||
configServices,
|
||||
configVolumes,
|
||||
ps,
|
||||
push,
|
||||
restartAll,
|
||||
restartMany,
|
||||
restartOne,
|
||||
logs,
|
||||
port,
|
||||
version
|
||||
}
|
||||
|
|
|
|||
38
src/map-ports.ts
Normal file
38
src/map-ports.ts
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
const mapPorts = (
|
||||
ports: string
|
||||
): Array<{
|
||||
mapped?: { address: string; port: number }
|
||||
exposed: { port: number; protocol: string }
|
||||
}> => {
|
||||
if (!ports) {
|
||||
return []
|
||||
}
|
||||
|
||||
return ports.split(',').map((untypedPort) => {
|
||||
const exposedFragments = untypedPort.trim().split('->')
|
||||
|
||||
const [port, protocol] =
|
||||
exposedFragments.length === 1
|
||||
? exposedFragments[0].split('/')
|
||||
: exposedFragments[1].split('/')
|
||||
|
||||
const mapped = exposedFragments[0]
|
||||
const lastDoubleColon = mapped.lastIndexOf(':')
|
||||
|
||||
if (lastDoubleColon === -1) {
|
||||
return {
|
||||
exposed: { port: Number(port), protocol }
|
||||
}
|
||||
}
|
||||
|
||||
const address = mapped.substr(0, lastDoubleColon)
|
||||
const mappedPort = mapped.substr(lastDoubleColon + 1)
|
||||
|
||||
return {
|
||||
exposed: { port: Number(port), protocol },
|
||||
mapped: { port: Number(mappedPort), address }
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export default mapPorts
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
version: '2'
|
||||
|
||||
services:
|
||||
db:
|
||||
web:
|
||||
image: nginx:1.16.0
|
||||
container_name: compose_test_nginx_2
|
||||
container_name: compose_test_web_2
|
||||
command: 'nginx -g "daemon off;"'
|
||||
environment:
|
||||
NGINX_PORT: 5432
|
||||
NGINX_PORT: 8888
|
||||
ports:
|
||||
- "5432"
|
||||
- 8888:8888
|
||||
|
|
|
|||
|
|
@ -2,9 +2,10 @@ version: '3'
|
|||
|
||||
services:
|
||||
some-service:
|
||||
image: alpine:3.7.3
|
||||
image: nginx:1.19.9-alpine
|
||||
command: 'nginx -g "daemon off;"'
|
||||
volumes:
|
||||
- ./volume:/mountedvolume
|
||||
# - ./volume:/mountedvolume
|
||||
- db-data:/mountedsecondvolume
|
||||
|
||||
volumes:
|
||||
|
|
|
|||
|
|
@ -1,10 +1,17 @@
|
|||
version: '2'
|
||||
|
||||
services:
|
||||
db:
|
||||
web:
|
||||
image: nginx:1.16.0
|
||||
container_name: compose_test_nginx
|
||||
container_name: compose_test_web
|
||||
command: 'nginx -g "daemon off;"'
|
||||
alpine:
|
||||
image: alpine:3.7.3
|
||||
container_name: compose_test_alpine
|
||||
ports:
|
||||
- '0.0.0.0:80:80'
|
||||
- '0.0.0.0:443:443'
|
||||
proxy:
|
||||
image: nginx:1.19.9-alpine
|
||||
container_name: compose_test_proxy
|
||||
command: 'nginx -g "daemon off;"'
|
||||
hello:
|
||||
image: hello-world
|
||||
container_name: compose_test_hello
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
58
test/map-ports.test.ts
Normal file
58
test/map-ports.test.ts
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
import mapPorts from '../src/map-ports'
|
||||
|
||||
test('map ports for empty string', () => {
|
||||
expect(mapPorts('')).toEqual([])
|
||||
})
|
||||
|
||||
test('map ports for exposed tcp', () => {
|
||||
expect(mapPorts('80/tcp')).toEqual([
|
||||
{ exposed: { port: 80, protocol: 'tcp' } }
|
||||
])
|
||||
})
|
||||
|
||||
test('map ports for exposed tcp on ivp4 interface', () => {
|
||||
expect(mapPorts('0.0.0.0:443->443/tcp')).toEqual([
|
||||
{
|
||||
exposed: { port: 443, protocol: 'tcp' },
|
||||
mapped: { address: '0.0.0.0', port: 443 }
|
||||
}
|
||||
])
|
||||
})
|
||||
|
||||
test('map multiple tcp ports exposed on ivp4 interfaces', () => {
|
||||
expect(mapPorts('0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp')).toEqual([
|
||||
{
|
||||
exposed: { port: 443, protocol: 'tcp' },
|
||||
mapped: { address: '0.0.0.0', port: 443 }
|
||||
},
|
||||
{
|
||||
exposed: { port: 80, protocol: 'tcp' },
|
||||
mapped: { address: '0.0.0.0', port: 80 }
|
||||
}
|
||||
])
|
||||
})
|
||||
|
||||
test('map multiple tcp ports exposed on ipv4 and ipv6 interfaces', () => {
|
||||
expect(
|
||||
mapPorts(
|
||||
'0.0.0.0:443->443/tcp,:::443->443/tcp, 0.0.0.0:80->80/tcp,:::80->80/tcp'
|
||||
)
|
||||
).toEqual([
|
||||
{
|
||||
exposed: { port: 443, protocol: 'tcp' },
|
||||
mapped: { address: '0.0.0.0', port: 443 }
|
||||
},
|
||||
{
|
||||
exposed: { port: 443, protocol: 'tcp' },
|
||||
mapped: { address: '::', port: 443 }
|
||||
},
|
||||
{
|
||||
exposed: { port: 80, protocol: 'tcp' },
|
||||
mapped: { address: '0.0.0.0', port: 80 }
|
||||
},
|
||||
{
|
||||
exposed: { port: 80, protocol: 'tcp' },
|
||||
mapped: { address: '::', port: 80 }
|
||||
}
|
||||
])
|
||||
})
|
||||
Loading…
Reference in a new issue