docker api
This commit is contained in:
parent
b5ba9856ed
commit
b53509aa69
5 changed files with 110 additions and 3 deletions
15
README.md
15
README.md
|
@ -74,6 +74,7 @@ services:
|
|||
container_name: flame
|
||||
volumes:
|
||||
- <host_dir>:/app/data
|
||||
- /var/run/docker.sock:/var/sock/docker.sock # Docker socket
|
||||
ports:
|
||||
- 5005:5005
|
||||
restart: unless-stopped
|
||||
|
@ -155,6 +156,20 @@ To use search bar you need to type your search query with selected prefix. For e
|
|||
- Format: `www.domain.com`, `domain.com`, `sub.domain.com`, `local`, `ip`, `ip:port`
|
||||
- Redirect: `http://{dest}`
|
||||
|
||||
### Docker integration
|
||||
|
||||
In order to use the Docker integration, each container must have the following labels:
|
||||
|
||||
```yml
|
||||
labels:
|
||||
- flame.type=application # "app" works too
|
||||
- flame.name=My container
|
||||
- flame.url=https://example.com
|
||||
- flame.icon=icon-name # Optional, default is "docker"
|
||||
```
|
||||
|
||||
And you must have activated the Docker sync option in the settings panel.
|
||||
|
||||
### Custom CSS
|
||||
|
||||
> This is an experimental feature. Its behaviour might change in the future.
|
||||
|
|
|
@ -40,7 +40,9 @@ const OtherSettings = (props: ComponentProps): JSX.Element => {
|
|||
useOrdering: 'createdAt',
|
||||
appsSameTab: 0,
|
||||
bookmarksSameTab: 0,
|
||||
searchSameTab: 0
|
||||
searchSameTab: 0,
|
||||
dockerApps:1,
|
||||
unpinStoppedApps: 1
|
||||
})
|
||||
|
||||
// Get config
|
||||
|
@ -57,7 +59,9 @@ const OtherSettings = (props: ComponentProps): JSX.Element => {
|
|||
useOrdering: searchConfig('useOrdering', 'createdAt'),
|
||||
appsSameTab: searchConfig('appsSameTab', 0),
|
||||
bookmarksSameTab: searchConfig('bookmarksSameTab', 0),
|
||||
searchSameTab: searchConfig('searchSameTab', 0)
|
||||
searchSameTab: searchConfig('searchSameTab', 0),
|
||||
dockerApps: searchConfig('dockerApps', 1),
|
||||
unpinStoppedApps: searchConfig('unpinStoppedApps', 1)
|
||||
})
|
||||
}, [props.loading]);
|
||||
|
||||
|
@ -243,6 +247,31 @@ const OtherSettings = (props: ComponentProps): JSX.Element => {
|
|||
<option value={0}>False</option>
|
||||
</select>
|
||||
</InputGroup>
|
||||
<h2 className={classes.SettingsSection}>Docker</h2>
|
||||
<InputGroup>
|
||||
<label htmlFor='dockerApps'>Use Docker API</label>
|
||||
<select
|
||||
id='dockerApps'
|
||||
name='dockerApps'
|
||||
value={formData.dockerApps}
|
||||
onChange={(e) => inputChangeHandler(e, true)}
|
||||
>
|
||||
<option value={1}>True</option>
|
||||
<option value={0}>False</option>
|
||||
</select>
|
||||
</InputGroup>
|
||||
<InputGroup>
|
||||
<label htmlFor='unpinStoppedApps'>Unpin stopped containers / other apps</label>
|
||||
<select
|
||||
id='unpinStoppedApps'
|
||||
name='unpinStoppedApps'
|
||||
value={formData.unpinStoppedApps}
|
||||
onChange={(e) => inputChangeHandler(e, true)}
|
||||
>
|
||||
<option value={1}>True</option>
|
||||
<option value={0}>False</option>
|
||||
</select>
|
||||
</InputGroup>
|
||||
<Button>Save changes</Button>
|
||||
</form>
|
||||
)
|
||||
|
|
|
@ -18,4 +18,6 @@ export interface SettingsForm {
|
|||
appsSameTab: number;
|
||||
bookmarksSameTab: number;
|
||||
searchSameTab: number;
|
||||
dockerApps: number;
|
||||
unpinStoppedApps: number;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ const ErrorResponse = require('../utils/ErrorResponse');
|
|||
const App = require('../models/App');
|
||||
const Config = require('../models/Config');
|
||||
const { Sequelize } = require('sequelize');
|
||||
const axios = require('axios');
|
||||
|
||||
// @desc Create new app
|
||||
// @route POST /api/apps
|
||||
|
@ -45,10 +46,61 @@ exports.getApps = asyncWrapper(async (req, res, next) => {
|
|||
const useOrdering = await Config.findOne({
|
||||
where: { key: 'useOrdering' }
|
||||
});
|
||||
const useDockerApi = await Config.findOne({
|
||||
where: { key: 'dockerApps' }
|
||||
});
|
||||
const unpinStoppedApps = await Config.findOne({
|
||||
where: { key: 'unpinStoppedApps' }
|
||||
});
|
||||
|
||||
const orderType = useOrdering ? useOrdering.value : 'createdAt';
|
||||
let apps;
|
||||
|
||||
|
||||
if (useDockerApi && useDockerApi.value==1) {
|
||||
let {data:containers} = await axios.get('http://localhost/containers/json?{"status":["running"]}', {
|
||||
socketPath: '/var/run/docker.sock'
|
||||
});
|
||||
|
||||
if (containers) {
|
||||
apps = await App.findAll({
|
||||
order: [[ orderType, 'ASC' ]]
|
||||
});
|
||||
|
||||
containers = containers.filter((e) => Object.keys(e.Labels).length !== 0);
|
||||
const dockerApps = [];
|
||||
for (const container of containers) {
|
||||
const labels = container.Labels;
|
||||
|
||||
if ('flame.name' in labels && 'flame.url' in labels && (labels['flame.type']==='application' || labels['flame.type']==='app')) {
|
||||
dockerApps.push({
|
||||
name: labels['flame.name'],
|
||||
url: labels['flame.url'],
|
||||
icon: labels['flame.icon'] || 'docker'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (unpinStoppedApps && unpinStoppedApps.value==1) {
|
||||
for (const app of apps) {
|
||||
await app.update({ isPinned: false });
|
||||
}
|
||||
}
|
||||
|
||||
for (const item of dockerApps) {
|
||||
if (apps.some(app => app.name === item.name)) {
|
||||
const app = apps.filter(e => e.name === item.name)[0];
|
||||
await app.update({ ...item,isPinned: true });
|
||||
} else {
|
||||
await App.create({
|
||||
...item,
|
||||
isPinned: true
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (orderType == 'name') {
|
||||
apps = await App.findAll({
|
||||
order: [[ Sequelize.fn('lower', Sequelize.col('name')), 'ASC' ]]
|
||||
|
@ -59,7 +111,8 @@ exports.getApps = asyncWrapper(async (req, res, next) => {
|
|||
});
|
||||
}
|
||||
|
||||
res.status(200).json({
|
||||
// Set header to fetch containers info every time
|
||||
res.status(200).setHeader('Cache-Control','no-store').json({
|
||||
success: true,
|
||||
data: apps
|
||||
})
|
||||
|
|
|
@ -63,6 +63,14 @@
|
|||
{
|
||||
"key": "defaultSearchProvider",
|
||||
"value": "d"
|
||||
},
|
||||
{
|
||||
"key": "dockerApps",
|
||||
"value": true
|
||||
},
|
||||
{
|
||||
"key": "unpinStoppedApps",
|
||||
"value": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue