mirror of
https://github.com/containers/podman-compose.git
synced 2025-07-01 21:20:18 +02:00
Compare commits
588 Commits
Author | SHA1 | Date | |
---|---|---|---|
9cbc4c1dcd | |||
c63d678887 | |||
6de335beb2 | |||
23799245bd | |||
eda4815715 | |||
cbb0cab814 | |||
7c8696b2b2 | |||
483103ac3a | |||
e9f1029406 | |||
804852b218 | |||
0e3b372a29 | |||
f11e08eaac | |||
62789a2358 | |||
35cf4bcb72 | |||
9964604b17 | |||
61fa24bf21 | |||
ac7ec5c166 | |||
75d7be2b7b | |||
346f7a57f0 | |||
55642247e3 | |||
978a1381bc | |||
4a232f5e32 | |||
aa8c6fd598 | |||
fb0bbd6fe1 | |||
b324029f25 | |||
590c371db2 | |||
16196a1f6d | |||
2dfbb59097 | |||
a34d1d1a31 | |||
d6da65e6c9 | |||
de2c33d7ae | |||
2891be01d7 | |||
a023dc145b | |||
d803c4c3e8 | |||
420d19daf4 | |||
2cfc617f9e | |||
376f0817e6 | |||
054c66b568 | |||
d9fc8e91f2 | |||
145ae47c48 | |||
a67fa0beb5 | |||
3ba0396e7a | |||
973e15ba23 | |||
002c2e400b | |||
626e278794 | |||
a358890d54 | |||
9f3251ff3d | |||
a9cfdb6704 | |||
c0dc3e47fd | |||
41e69be201 | |||
4ae6ccb5c0 | |||
4203f799ee | |||
69e95be2f6 | |||
122a914b9b | |||
db0aad97bd | |||
a3fb4b373a | |||
ab33954f6c | |||
4660feb04a | |||
90f54b9ca5 | |||
7090de3bce | |||
df8fa588a5 | |||
e2ae8bee04 | |||
5c81bbfcb7 | |||
22b0c4b348 | |||
380cf42dcd | |||
deed4d51b0 | |||
08b3ac2633 | |||
f8ea85e3af | |||
0de7e13f1a | |||
da7fd4fe86 | |||
cb294d7519 | |||
351858dbec | |||
8d0dd214ae | |||
229650cba8 | |||
ab832d23c7 | |||
4a7329b9e3 | |||
de3f93c491 | |||
54cc055a5c | |||
f4bf69b68e | |||
5297b004af | |||
fd1fc833b0 | |||
124879a7b9 | |||
368efe2ee3 | |||
eeefd37996 | |||
b7514a0647 | |||
561094954d | |||
ea239c4b77 | |||
9fdee76858 | |||
0a6e0a35e1 | |||
26e6651d6c | |||
462603383c | |||
8411db49d1 | |||
fc90f60bf1 | |||
ed58ac0879 | |||
305f25b4d6 | |||
edadf73d82 | |||
dc04108b3e | |||
348461ca77 | |||
92dbd3690e | |||
a1e9a82693 | |||
9e11c6bfbc | |||
0d24c41afb | |||
585d344d0a | |||
3aa6d4d158 | |||
34f5268e37 | |||
b5eaf314ad | |||
b3c49df6eb | |||
dbbd695463 | |||
1b1d3d8c25 | |||
7d7e64fe5a | |||
3c9c18c6e0 | |||
d0a2a44442 | |||
1e66c28bbb | |||
b6eadd56b1 | |||
d95b4d026b | |||
e2eb883709 | |||
0866492a7e | |||
85050097e5 | |||
daab93b762 | |||
9fe30387ee | |||
0f8348bea7 | |||
55ab3fa7f7 | |||
2091ade7b1 | |||
ca58d7cd58 | |||
3296c8d34f | |||
dab6b1b98d | |||
5bf4c0fdbe | |||
67c5352c3a | |||
5e0f7e5e19 | |||
5040a37d47 | |||
c82859b89f | |||
29195be77c | |||
1c74d6cd11 | |||
9a4af0ce62 | |||
0517b9e34c | |||
24038dace3 | |||
0ea4cbe091 | |||
2056e703d5 | |||
137c6207b2 | |||
4ec57c1013 | |||
d9a3572461 | |||
fa3e0a7772 | |||
0bcf0799b6 | |||
18472b53ac | |||
d38b26bb01 | |||
22a4ad5806 | |||
37e2cb28d4 | |||
0cd3902c5f | |||
6ef759c6fd | |||
16cbcf4152 | |||
67ce900885 | |||
4e9f76768c | |||
84f7fdd7da | |||
405001b990 | |||
6b1aeff55f | |||
f06975b346 | |||
546cad5171 | |||
e07c28d127 | |||
935029dc33 | |||
80b2aa6ed0 | |||
360b85bf2d | |||
650a835eca | |||
82740cc311 | |||
0f645e4c70 | |||
3b15170ccf | |||
3359380ec6 | |||
14f39e5b86 | |||
e799a0b0ea | |||
6d8d3e94fe | |||
65d1fdeaa3 | |||
d905a7c638 | |||
2e8ed2f924 | |||
040b73adab | |||
f3e9a96c96 | |||
04b107805a | |||
2c5d00d3e7 | |||
cac90f69b8 | |||
b513f50f30 | |||
8f618b6fab | |||
cac836b0f5 | |||
3bb305cef4 | |||
09034a0c38 | |||
e668a339ce | |||
0065082db9 | |||
5d4de80ab7 | |||
23ad5c3ef7 | |||
45efe461b0 | |||
4f73f2b79e | |||
1d64f2cf8c | |||
2ce6d1a1e7 | |||
4e22faefd6 | |||
7a2da76ab8 | |||
79865c2e13 | |||
33d7d35a4d | |||
c23a8b2cbd | |||
36a3d3c207 | |||
b202a09501 | |||
35cbc49160 | |||
5c4aa40032 | |||
0ee7c2630a | |||
cef1785cd5 | |||
b4cfef12e9 | |||
b761050b0b | |||
e1d0ea7b4e | |||
1430578568 | |||
8f41cd3cdb | |||
a73dac2e39 | |||
d31a8b124d | |||
5df4e786ee | |||
27e27e9fe9 | |||
70a0e2d003 | |||
58641f0545 | |||
eea8bac496 | |||
09a8a3edf9 | |||
a6c4263738 | |||
9599cc039e | |||
0a6c057486 | |||
2b4ecee082 | |||
77f2e8e5b0 | |||
12d46ca836 | |||
72a94d5185 | |||
2681566580 | |||
62ce087c6e | |||
c97f003732 | |||
c88558b4ec | |||
131010bc9d | |||
1da2f85a90 | |||
cdcedeb6b2 | |||
3e1f7d554b | |||
d7cf0966d3 | |||
e893d06313 | |||
1f35c00694 | |||
9a5b43907f | |||
6c09ce710e | |||
953534a71a | |||
6feff244db | |||
9fd4cf43c1 | |||
65849c95e2 | |||
9baea704d7 | |||
bdff78dcba | |||
45ca1f994f | |||
91fbea3d89 | |||
2743d690d2 | |||
dd34a90068 | |||
6103df78fb | |||
07128f6b37 | |||
f0bae1e2d9 | |||
81d81fb303 | |||
b263dc1a7d | |||
078ee7b649 | |||
a6e3ae7b31 | |||
1e9cf1dff0 | |||
d704622522 | |||
bbfff78e25 | |||
abb0cb1649 | |||
d53df307f8 | |||
c351f99da5 | |||
829cde0de9 | |||
f18c8092cc | |||
43059dc16f | |||
da63048775 | |||
7987a7185e | |||
5e55df890c | |||
fde7995cb8 | |||
c592596a5e | |||
688ee9a104 | |||
c3a152e68f | |||
bd60bc9f21 | |||
9d8b0b8632 | |||
ee013316c0 | |||
f2f5483a74 | |||
c4fa8f7a16 | |||
4c270b9116 | |||
c5f7f550f9 | |||
c98cbaaaf0 | |||
f2f2f15a3b | |||
91d316ff1f | |||
121b5f6ea1 | |||
969edb88d0 | |||
bba1f33d51 | |||
970e4ac4ab | |||
a9c335bf82 | |||
e67c52f2c4 | |||
e0fc9a7546 | |||
2cdfb3e6d4 | |||
60137eb7f9 | |||
a7a993faef | |||
8ec5e0372a | |||
da520e299b | |||
1e9e2ee776 | |||
dcb6cdb55a | |||
0f693ee584 | |||
d468f85fd1 | |||
cf90ab2858 | |||
d2fa80196f | |||
247774822c | |||
6e65a73ab9 | |||
f95ca7aca7 | |||
cdf5961bf2 | |||
0c0e77c246 | |||
e6fc585702 | |||
bb2338e447 | |||
a8db898ac6 | |||
1ba1c364b9 | |||
15ae2140d4 | |||
ed39523342 | |||
4e43606df3 | |||
91052cb2d9 | |||
a6e0092627 | |||
59a1fa3942 | |||
36139fb282 | |||
b0da6f82d3 | |||
b1e4324d41 | |||
94df95acea | |||
3a5a283cf6 | |||
16a90e2bce | |||
7c81044860 | |||
5b571942e0 | |||
de8f545f07 | |||
1a24cde608 | |||
a90da4dfaf | |||
6841619b9c | |||
27c8cebbdc | |||
c84b4c33fc | |||
0614687840 | |||
a494f20e15 | |||
6af7a2d691 | |||
872664b727 | |||
f4dc5f3b93 | |||
ac5034065d | |||
b34f699adb | |||
3d68d2432d | |||
2c6c1be197 | |||
f81cbe39b5 | |||
91737ee0a6 | |||
9d1407ba90 | |||
b65d4a3916 | |||
23fe9e7e1d | |||
7539257ee8 | |||
9e29891aa7 | |||
a967cab02b | |||
a5c354d60b | |||
e4e5b7d461 | |||
e0edd5dac1 | |||
831caa6276 | |||
9ac33392a0 | |||
c5be5bae90 | |||
c6a1c4c432 | |||
3c9628b462 | |||
38b13a34ea | |||
bce40c2db3 | |||
78f8cad7c4 | |||
7942a540cd | |||
cb9cf6002f | |||
06587c1dca | |||
bc9168b039 | |||
57c527c2c9 | |||
d1f5ac9edc | |||
0164c1db56 | |||
e5cdce4e7d | |||
280f1770bf | |||
f75d12af21 | |||
5454c3ad0f | |||
901adf47d0 | |||
bf07e91163 | |||
c31b4e2816 | |||
3890eacf57 | |||
cfd24cc2e8 | |||
79bfad103c | |||
d1509468c3 | |||
9011e9faa1 | |||
517aeba330 | |||
85d5d5dcc9 | |||
1ffd24dcf9 | |||
8c66b1cda7 | |||
a0005db474 | |||
221cf14501 | |||
a61945b516 | |||
6b6330c587 | |||
5d279c4948 | |||
5a3bdbf89b | |||
1eb166445b | |||
82182b7bc6 | |||
3f4618866b | |||
91bc6ebdb4 | |||
59a59c1a3a | |||
620f5d7473 | |||
6f902faed0 | |||
ccdf01e9b0 | |||
e6b1eabe4c | |||
75de39c239 | |||
874192568f | |||
0b853f29f4 | |||
847f01a6c6 | |||
e511e6420f | |||
a9723ec1cf | |||
1cb608d8a7 | |||
252f1d57a5 | |||
13856d2e9c | |||
8d8df0bc28 | |||
bc5f0123d9 | |||
9a08f85ffd | |||
8625d7a4e8 | |||
016c97fd1e | |||
2df11674c4 | |||
5eff38e743 | |||
7f5ce26b1b | |||
f6dbce3618 | |||
dfb64d884d | |||
990f774659 | |||
5e518c7ca7 | |||
9046f7eee0 | |||
ef55067834 | |||
ed2a6c0917 | |||
b4c0792995 | |||
e84451f4ea | |||
456370bd46 | |||
efe3714266 | |||
c55a2f4c26 | |||
b8a7593026 | |||
bd29ddb3e9 | |||
38219eb85c | |||
08ffcf6126 | |||
801faea30b | |||
06da9667f3 | |||
de3f607758 | |||
db1861d33f | |||
9d5b255927 | |||
2d05c5c339 | |||
3c460160e0 | |||
5b9cfe5d17 | |||
8d1a4d7274 | |||
859f03cbe6 | |||
ae6be272b5 | |||
ccdb98c0e4 | |||
909d05e718 | |||
0cf98c7893 | |||
843b876885 | |||
1188463734 | |||
10580db329 | |||
f7d335dc6a | |||
4a73ae86bc | |||
f674ab8cfb | |||
265e0ca32a | |||
92662f3409 | |||
42c0078e6b | |||
da5ee723c3 | |||
06fc0715fe | |||
9eda56caf9 | |||
13c8981c6d | |||
ee7029fbde | |||
75033a4ed7 | |||
c175fd1b10 | |||
d479001454 | |||
a2defdd06a | |||
c55cd67bd2 | |||
eed38ce76c | |||
86ffad86c7 | |||
118d39b5bb | |||
814bd2a31a | |||
606b9d94c8 | |||
0057a4bb31 | |||
8ecb74916d | |||
d983056982 | |||
ed302ca518 | |||
0b5c844431 | |||
9c29c8914f | |||
89d2062579 | |||
f42b568fc2 | |||
a1d3ba4ea2 | |||
6be661f6da | |||
fc3598faf2 | |||
fbff315e18 | |||
fc34703dd4 | |||
c7ada820de | |||
5e286f6356 | |||
3dd8b05d74 | |||
3ecb4b5dd5 | |||
d05cad4c65 | |||
ebb3dfe634 | |||
7b99b38f0e | |||
4ef8afc63e | |||
a1aed09a58 | |||
2cacf9cfb5 | |||
4064c84521 | |||
0dde95ac1d | |||
1be41b46a5 | |||
105c27c8dc | |||
f820594257 | |||
8a72321720 | |||
529391963d | |||
48a19f13fc | |||
a9faabb1b0 | |||
3fb2b98ecc | |||
b35b7e448a | |||
1a72e1e087 | |||
b620311aaf | |||
bf8004b04d | |||
cadf046306 | |||
8d8149cfe5 | |||
3dd981727b | |||
0b469e0590 | |||
9e3020a9df | |||
fc9ed19b2b | |||
2d6bb52e36 | |||
7942a091c3 | |||
701311aa7a | |||
d7049150d0 | |||
3b7bf81051 | |||
a735aa5b96 | |||
b78509527b | |||
762318093c | |||
af10345483 | |||
2d1bcddf09 | |||
4f025679cf | |||
064521255b | |||
b7c5609603 | |||
44508352e8 | |||
5c33e4efbb | |||
cbd6f6b1b6 | |||
de1e59d1d5 | |||
2f0ca9e41d | |||
59c9a69689 | |||
b7eac1e898 | |||
0d47e470fc | |||
c2d7b26f2e | |||
1e895c0873 | |||
132a22b524 | |||
0bde01de07 | |||
91a579b81e | |||
56b88639ad | |||
5c3ec5f49a | |||
779198b003 | |||
40cb6a760e | |||
4fd9d86e17 | |||
2a2c3a09c1 | |||
80e852717d | |||
d6e21dc752 | |||
b9b2f83d04 | |||
9af65ea112 | |||
3e6e268034 | |||
af6a3069ce | |||
68f745fe62 | |||
90dcfdbf44 | |||
ed8635a9a3 | |||
1d972ef174 | |||
536925ca78 | |||
09c6cbe503 | |||
154a51245f | |||
523d215b48 | |||
25494b5f6e | |||
19662c02a1 | |||
4943e52344 | |||
4aa08cd016 | |||
15e0ab9261 | |||
f66861f89a | |||
af53b65068 | |||
890c584881 | |||
0bd493f1ba | |||
481c6d0a41 | |||
31df70b8d2 | |||
df400518a7 | |||
21a716cfd3 | |||
f00ac92640 | |||
0433410702 | |||
0f9fe2bf9f | |||
a1be5ce6b3 | |||
56a4988481 | |||
377b5525c9 | |||
c50599c0e7 | |||
4557279930 | |||
7ad377557d | |||
30051c2f5b | |||
9e8e25c159 | |||
2c60516f77 | |||
24ec539932 | |||
2803046ac3 | |||
d1768c1d9d | |||
820ea012c5 | |||
5ba96a1082 | |||
49fe6e7e0f | |||
6c1ccfcefa | |||
724d2fd18c | |||
3e940579d9 | |||
af1697e9bf | |||
e62f1a54af | |||
179f9ab0e3 | |||
dd6b1ee88c |
1
.codespellignore
Normal file
1
.codespellignore
Normal file
@ -0,0 +1 @@
|
|||||||
|
assertIn
|
4
.codespellrc
Normal file
4
.codespellrc
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[codespell]
|
||||||
|
skip = .git,*.pdf,*.svg,requirements.txt,test-requirements.txt
|
||||||
|
# poped - loved variable name
|
||||||
|
ignore-words-list = poped
|
2
.coveragerc
Normal file
2
.coveragerc
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[run]
|
||||||
|
parallel=True
|
19
.editorconfig
Normal file
19
.editorconfig
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = tab
|
||||||
|
tab_width = 4
|
||||||
|
end_of_line = lf
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
max_line_length = 100
|
||||||
|
|
||||||
|
[*.{yml,yaml}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.py]
|
||||||
|
indent_style = space
|
||||||
|
|
4
.github/ISSUE_TEMPLATE/bug_report.md
vendored
4
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -13,8 +13,6 @@ A clear and concise description of what the bug is.
|
|||||||
Please make sure it's not a bug in podman (in that case report it to podman)
|
Please make sure it's not a bug in podman (in that case report it to podman)
|
||||||
or your understanding of docker-compose or how rootless containers work (for example, it's normal for rootless container not to be able to listen for port less than 1024 like 80)
|
or your understanding of docker-compose or how rootless containers work (for example, it's normal for rootless container not to be able to listen for port less than 1024 like 80)
|
||||||
|
|
||||||
please try to reproduce the bug in latest devel branch
|
|
||||||
|
|
||||||
**To Reproduce**
|
**To Reproduce**
|
||||||
Steps to reproduce the behavior:
|
Steps to reproduce the behavior:
|
||||||
1. what is the content of the current working directory (ex. `docker-compose.yml`, `.env`, `Dockerfile`, ...etc.)
|
1. what is the content of the current working directory (ex. `docker-compose.yml`, `.env`, `Dockerfile`, ...etc.)
|
||||||
@ -35,7 +33,7 @@ What is the behavior you actually got and that should not happen.
|
|||||||
```
|
```
|
||||||
$ podman-compose version
|
$ podman-compose version
|
||||||
using podman version: 3.4.0
|
using podman version: 3.4.0
|
||||||
podman-composer version 0.1.7dev
|
podman-compose version 0.1.7dev
|
||||||
podman --version
|
podman --version
|
||||||
podman version 3.4.0
|
podman version 3.4.0
|
||||||
|
|
||||||
|
10
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
10
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
## Contributor Checklist:
|
||||||
|
|
||||||
|
If this PR adds a new feature that improves compatibility with docker-compose, please add a link
|
||||||
|
to the exact part of compose spec that the PR touches.
|
||||||
|
|
||||||
|
For any user-visible change please add a release note to newsfragments directory, e.g.
|
||||||
|
newsfragments/my_feature.feature. See newsfragments/README.md for more details.
|
||||||
|
|
||||||
|
All changes require additional unit tests.
|
6
.github/dependabot.yml
vendored
Normal file
6
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
22
.github/workflows/codespell.yml
vendored
Normal file
22
.github/workflows/codespell.yml
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
name: Codespell
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
codespell:
|
||||||
|
name: Check for spelling errors
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Codespell
|
||||||
|
uses: codespell-project/actions-codespell@v2
|
||||||
|
with:
|
||||||
|
ignore_words_file: .codespellignore
|
27
.github/workflows/release.yml
vendored
Normal file
27
.github/workflows/release.yml
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
name: Build and Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*.*.*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Build binary
|
||||||
|
run: |
|
||||||
|
mkdir -p release/
|
||||||
|
docker build -t podman-compose-bin -v "$PWD/release:/result" .
|
||||||
|
mv "$PWD/release/podman-compose" "$PWD/release/podman-compose-linux-x86"
|
||||||
|
|
||||||
|
- name: Upload release asset
|
||||||
|
uses: softprops/action-gh-release@v2
|
||||||
|
with:
|
||||||
|
files: ./release/podman-compose-linux-x86
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
25
.github/workflows/static-checks.yml
vendored
Normal file
25
.github/workflows/static-checks.yml
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
name: Static checks
|
||||||
|
|
||||||
|
on:
|
||||||
|
- push
|
||||||
|
- pull_request
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
static-checks:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: docker.io/library/python:3.11-bookworm
|
||||||
|
# cgroupns needed to address the following error:
|
||||||
|
# write /sys/fs/cgroup/cgroup.subtree_control: operation not supported
|
||||||
|
options: --privileged --cgroupns=host
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Analysing the code with ruff
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
pip install -r test-requirements.txt
|
||||||
|
ruff format --check
|
||||||
|
ruff check
|
||||||
|
- name: Analysing the code with pylint
|
||||||
|
run: |
|
||||||
|
pylint podman_compose.py
|
40
.github/workflows/test.yml
vendored
Normal file
40
.github/workflows/test.yml
vendored
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
name: Tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
python-version: [ '3.9', '3.10', '3.11', '3.12', '3.13' ]
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: "docker.io/library/python:${{ matrix.python-version }}-bookworm"
|
||||||
|
# cgroupns needed to address the following error:
|
||||||
|
# write /sys/fs/cgroup/cgroup.subtree_control: operation not supported
|
||||||
|
options: --privileged --cgroupns=host
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y podman
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install -r requirements.txt
|
||||||
|
pip install -r test-requirements.txt
|
||||||
|
- name: Run integration tests
|
||||||
|
run: |
|
||||||
|
python -m unittest discover -v tests/integration
|
||||||
|
env:
|
||||||
|
TESTS_DEBUG: 1
|
||||||
|
- name: Run unit tests
|
||||||
|
run: |
|
||||||
|
coverage run --source podman_compose -m unittest discover tests/unit
|
||||||
|
- name: Report coverage
|
||||||
|
run: |
|
||||||
|
coverage combine
|
||||||
|
coverage report --format=markdown | tee -a $GITHUB_STEP_SUMMARY
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -47,6 +47,8 @@ coverage.xml
|
|||||||
*.cover
|
*.cover
|
||||||
.hypothesis/
|
.hypothesis/
|
||||||
.pytest_cache/
|
.pytest_cache/
|
||||||
|
test-compose.yaml
|
||||||
|
test-compose-?.yaml
|
||||||
|
|
||||||
# Translations
|
# Translations
|
||||||
*.mo
|
*.mo
|
||||||
@ -103,3 +105,6 @@ venv.bak/
|
|||||||
|
|
||||||
# mypy
|
# mypy
|
||||||
.mypy_cache/
|
.mypy_cache/
|
||||||
|
|
||||||
|
|
||||||
|
.vscode
|
||||||
|
36
.pre-commit-config.yaml
Normal file
36
.pre-commit-config.yaml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
repos:
|
||||||
|
- repo: https://github.com/psf/black
|
||||||
|
rev: 23.3.0
|
||||||
|
hooks:
|
||||||
|
- id: black
|
||||||
|
# It is recommended to specify the latest version of Python
|
||||||
|
# supported by your project here, or alternatively use
|
||||||
|
# pre-commit's default_language_version, see
|
||||||
|
# https://pre-commit.com/#top_level-default_language_version
|
||||||
|
language_version: python3.10
|
||||||
|
types: [python]
|
||||||
|
args: [
|
||||||
|
"--check", # Don't apply changes automatically
|
||||||
|
]
|
||||||
|
- repo: https://github.com/pycqa/flake8
|
||||||
|
rev: 6.0.0
|
||||||
|
hooks:
|
||||||
|
- id: flake8
|
||||||
|
types: [python]
|
||||||
|
- repo: local
|
||||||
|
hooks:
|
||||||
|
- id: pylint
|
||||||
|
name: pylint
|
||||||
|
entry: pylint
|
||||||
|
language: system
|
||||||
|
types: [python]
|
||||||
|
args:
|
||||||
|
[
|
||||||
|
"-rn", # Only display messages
|
||||||
|
"-sn", # Don't display the score
|
||||||
|
"--rcfile=.pylintrc", # Link to your config file
|
||||||
|
]
|
||||||
|
- repo: https://github.com/codespell-project/codespell
|
||||||
|
rev: v2.2.5
|
||||||
|
hooks:
|
||||||
|
- id: codespell
|
11
.pylintrc
11
.pylintrc
@ -1,13 +1,18 @@
|
|||||||
[MESSAGES CONTROL]
|
[MESSAGES CONTROL]
|
||||||
disable=W0614,C0410,C0321,C0111,I0011,C0103
|
# C0111 missing-docstring: missing-class-docstring, missing-function-docstring, missing-method-docstring, missing-module-docstrin
|
||||||
|
# consider-using-with: we need it for color formatter pipe
|
||||||
|
disable=too-many-lines,too-many-branches,too-many-locals,too-many-statements,too-many-arguments,too-many-instance-attributes,fixme,multiple-statements,missing-docstring,line-too-long,consider-using-f-string,consider-using-with,unnecessary-lambda-assignment
|
||||||
# allow _ for ignored variables
|
# allow _ for ignored variables
|
||||||
# allow generic names like a,b,c and i,j,k,l,m,n and x,y,z
|
# allow generic names like a,b,c and i,j,k,l,m,n and x,y,z
|
||||||
# allow k,v for key/value
|
# allow k,v for key/value
|
||||||
# allow e for exceptions, it for iterator
|
# allow e for exceptions, it for iterator, ix for index
|
||||||
|
# allow ip for ip address
|
||||||
# allow w,h for width, height
|
# allow w,h for width, height
|
||||||
# allow op for operation/operator/opcode
|
# allow op for operation/operator/opcode
|
||||||
# allow t, t0, t1, t2, and t3 for time
|
# allow t, t0, t1, t2, and t3 for time
|
||||||
# allow dt for delta time
|
# allow dt for delta time
|
||||||
# allow db for database
|
# allow db for database
|
||||||
# allow ls for list
|
# allow ls for list
|
||||||
good-names=_,a,b,c,dt,db,e,f,fn,fd,i,j,k,v,kv,kw,l,m,n,ls,t,t0,t1,t2,t3,w,h,x,y,z,it,op
|
# allow p for pipe
|
||||||
|
# allow ex for examples, exists ..etc
|
||||||
|
good-names=_,a,b,c,dt,db,e,f,fn,fd,i,j,k,v,kv,kw,l,m,n,ls,t,t0,t1,t2,t3,w,h,x,y,z,it,ix,ip,op,p,ex
|
||||||
|
137
CONTRIBUTING.md
137
CONTRIBUTING.md
@ -1,74 +1,135 @@
|
|||||||
# Contributing to podman-compose
|
# Contributing to podman-compose
|
||||||
|
|
||||||
|
## Who can contribute?
|
||||||
|
|
||||||
|
- Users that found a bug,
|
||||||
|
- Users that want to propose new functionalities or enhancements,
|
||||||
|
- Users that want to help other users to troubleshoot their environments,
|
||||||
|
- Developers that want to fix bugs,
|
||||||
|
- Developers that want to implement new functionalities or enhancements.
|
||||||
|
|
||||||
|
## Development environment setup
|
||||||
|
|
||||||
|
Note: Some steps are OPTIONAL but all are RECOMMENDED.
|
||||||
|
|
||||||
|
1. Fork the project repository and clone it:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ git clone https://github.com/USERNAME/podman-compose.git
|
||||||
|
$ cd podman-compose
|
||||||
|
```
|
||||||
|
|
||||||
|
2. (OPTIONAL) Create a Python virtual environment. Example using
|
||||||
|
[virtualenv wrapper](https://virtualenvwrapper.readthedocs.io/en/latest/):
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ mkvirtualenv podman-compose
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Install the project runtime and development requirements:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ pip install '.[devel]'
|
||||||
|
```
|
||||||
|
|
||||||
|
4. (OPTIONAL) Install `pre-commit` git hook scripts
|
||||||
|
(https://pre-commit.com/#3-install-the-git-hook-scripts):
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ pre-commit install
|
||||||
|
```
|
||||||
|
|
||||||
|
5. Create a new branch, develop and add tests when possible.
|
||||||
|
6. Run linting and testing before committing code. Ensure all the hooks are passing.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ pre-commit run --all-files
|
||||||
|
```
|
||||||
|
|
||||||
|
7. Run code coverage:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ coverage run --source podman_compose -m unittest discover tests/unit
|
||||||
|
$ python3 -m unittest discover tests/integration
|
||||||
|
$ coverage combine
|
||||||
|
$ coverage report
|
||||||
|
$ coverage html
|
||||||
|
```
|
||||||
|
|
||||||
|
8. Commit your code to your fork's branch.
|
||||||
|
- Make sure you include a `Signed-off-by` message in your commits.
|
||||||
|
Read [this guide](https://github.com/containers/common/blob/main/CONTRIBUTING.md#sign-your-prs)
|
||||||
|
to learn how to sign your commits.
|
||||||
|
- In the commit message, reference the Issue ID that your code fixes and a brief description of
|
||||||
|
the changes.
|
||||||
|
Example: `Fixes #516: Allow empty network`
|
||||||
|
9. Open a pull request to `containers/podman-compose` and wait for a maintainer to review your work.
|
||||||
|
|
||||||
## Adding new commands
|
## Adding new commands
|
||||||
|
|
||||||
To add a command you need to add a function that is decorated
|
To add a command, you need to add a function that is decorated with `@cmd_run`.
|
||||||
with `@cmd_run` passing the compose instance, command name and
|
|
||||||
description. the wrapped function should accept two arguments
|
|
||||||
the compose instance and the command-specific arguments (resulted
|
|
||||||
from python's `argparse` package) inside that command you can
|
|
||||||
run PodMan like this `compose.podman.run(['inspect', 'something'])`
|
|
||||||
and inside that function you can access `compose.pods`
|
|
||||||
and `compose.containers` ...etc.
|
|
||||||
Here is an example
|
|
||||||
|
|
||||||
```
|
The decorated function must be declared `async` and should accept two arguments: The compose
|
||||||
|
instance and the command-specific arguments (resulted from the Python's `argparse` package).
|
||||||
|
|
||||||
|
In this function, you can run Podman (e.g. `await compose.podman.run(['inspect', 'something'])`),
|
||||||
|
access `compose.pods`, `compose.containers` etc.
|
||||||
|
|
||||||
|
Here is an example:
|
||||||
|
|
||||||
|
```python
|
||||||
@cmd_run(podman_compose, 'build', 'build images defined in the stack')
|
@cmd_run(podman_compose, 'build', 'build images defined in the stack')
|
||||||
def compose_build(compose, args):
|
async def compose_build(compose, args):
|
||||||
compose.podman.run(['build', 'something'])
|
await compose.podman.run(['build', 'something'])
|
||||||
```
|
```
|
||||||
|
|
||||||
## Command arguments parsing
|
## Command arguments parsing
|
||||||
|
|
||||||
Add a function that accept `parser` which is an instance from `argparse`.
|
To add arguments to be parsed by a command, you need to add a function that is decorated with
|
||||||
In side that function you can call `parser.add_argument()`.
|
`@cmd_parse` which accepts the compose instance and the command's name (as a string list or as a
|
||||||
The function decorated with `@cmd_parse` accepting the compose instance,
|
single string).
|
||||||
and command names (as a list or as a string).
|
|
||||||
You can do this multiple times.
|
|
||||||
|
|
||||||
Here is an example
|
The decorated function should accept a single argument: An instance of `argparse`.
|
||||||
|
|
||||||
```
|
In this function, you can call `parser.add_argument()` to add a new argument to the command.
|
||||||
|
|
||||||
|
Note you can add such a function multiple times.
|
||||||
|
|
||||||
|
Here is an example:
|
||||||
|
|
||||||
|
```python
|
||||||
@cmd_parse(podman_compose, 'build')
|
@cmd_parse(podman_compose, 'build')
|
||||||
def compose_build_parse(parser):
|
def compose_build_parse(parser):
|
||||||
parser.add_argument("--pull",
|
parser.add_argument("--pull",
|
||||||
help="attempt to pull a newer version of the image", action='store_true')
|
help="attempt to pull a newer version of the image", action='store_true')
|
||||||
parser.add_argument("--pull-always",
|
parser.add_argument("--pull-always",
|
||||||
help="attempt to pull a newer version of the image, Raise an error even if the image is present locally.", action='store_true')
|
help="Attempt to pull a newer version of the image, "
|
||||||
|
"raise an error even if the image is present locally.",
|
||||||
|
action='store_true')
|
||||||
```
|
```
|
||||||
|
|
||||||
NOTE: `@cmd_parse` should be after `@cmd_run`
|
NOTE: `@cmd_parse` should be after `@cmd_run`.
|
||||||
|
|
||||||
## Calling a command from inside another
|
## Calling a command from another one
|
||||||
|
|
||||||
If you need to call `podman-compose down` from inside `podman-compose up`
|
If you need to call `podman-compose down` from `podman-compose up`, do something like:
|
||||||
do something like:
|
|
||||||
|
|
||||||
```
|
```python
|
||||||
@cmd_run(podman_compose, 'up', 'up desc')
|
@cmd_run(podman_compose, 'up', 'up desc')
|
||||||
def compose_up(compose, args):
|
async def compose_up(compose, args):
|
||||||
compose.commands['down'](compose, args)
|
await compose.commands['down'](compose, args)
|
||||||
# or
|
# or
|
||||||
compose.commands['down'](argparse.Namespace(foo=123))
|
await compose.commands['down'](argparse.Namespace(foo=123))
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Missing Commands (help needed)
|
## Missing Commands (help needed)
|
||||||
|
|
||||||
```
|
```
|
||||||
bundle Generate a Docker bundle from the Compose file
|
bundle Generate a Docker bundle from the Compose file
|
||||||
config Validate and view the Compose file
|
|
||||||
create Create services
|
create Create services
|
||||||
events Receive real time events from containers
|
events Receive real time events from containers
|
||||||
images List images
|
images List images
|
||||||
kill Kill containers
|
|
||||||
logs View output from containers
|
|
||||||
pause Pause services
|
|
||||||
port Print the public port for a port binding
|
|
||||||
ps List containers
|
|
||||||
rm Remove stopped containers
|
rm Remove stopped containers
|
||||||
run Run a one-off command
|
|
||||||
scale Set number of containers for a service
|
scale Set number of containers for a service
|
||||||
top Display the running processes
|
top Display the running processes
|
||||||
unpause Unpause services
|
|
||||||
version Show the Docker-Compose version information
|
|
||||||
```
|
```
|
||||||
|
30
Dockerfile
Normal file
30
Dockerfile
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# Use a base image with necessary build tools
|
||||||
|
FROM python:3.11-slim AS builder
|
||||||
|
|
||||||
|
# Install required packages for building
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
gcc \
|
||||||
|
musl-dev \
|
||||||
|
build-essential \
|
||||||
|
python3-dev \
|
||||||
|
&& apt-get clean \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Set the working directory
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy the application code
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Install PyInstaller
|
||||||
|
RUN pip install pyinstaller
|
||||||
|
RUN pip install -r requirements.txt
|
||||||
|
|
||||||
|
# Create a binary with PyInstaller
|
||||||
|
RUN pyinstaller --onefile --clean podman_compose.py
|
||||||
|
|
||||||
|
# Create /result dir in case it is not mounted
|
||||||
|
RUN mkdir -p /result
|
||||||
|
|
||||||
|
# Export binary
|
||||||
|
RUN cp /app/dist/podman_compose /result/podman-compose
|
70
README.md
70
README.md
@ -1,19 +1,25 @@
|
|||||||
# Podman Compose
|
# Podman Compose
|
||||||
|
## [](https://github.com/containers/podman-compose/actions/workflows/test.yml)
|
||||||
|
|
||||||
An implementation of [Compose Spec](https://compose-spec.io/) with [Podman](https://podman.io/) backend.
|
An implementation of [Compose Spec](https://compose-spec.io/) with [Podman](https://podman.io/) backend.
|
||||||
This project focus on:
|
This project focuses on:
|
||||||
|
|
||||||
* rootless
|
* rootless
|
||||||
* daemon-less process model, we directly execute podman, no running daemon.
|
* daemon-less process model, we directly execute podman, no running daemon.
|
||||||
|
|
||||||
This project only depend on:
|
This project only depends on:
|
||||||
|
|
||||||
* `podman`
|
* `podman`
|
||||||
|
* [podman dnsname plugin](https://github.com/containers/dnsname): It is usually found in
|
||||||
|
the `podman-plugins` or `podman-dnsname` distro packages, those packages are not pulled
|
||||||
|
by default and you need to install them. This allows containers to be able to resolve
|
||||||
|
each other if they are on the same CNI network. This is not necessary when podman is using
|
||||||
|
netavark as a network backend.
|
||||||
* Python3
|
* Python3
|
||||||
* [PyYAML](https://pyyaml.org/)
|
* [PyYAML](https://pyyaml.org/)
|
||||||
* [python-dotenv](https://pypi.org/project/python-dotenv/)
|
* [python-dotenv](https://pypi.org/project/python-dotenv/)
|
||||||
|
|
||||||
And it's formed as a single python file script that you can drop into your PATH and run.
|
And it's formed as a single Python file script that you can drop into your PATH and run.
|
||||||
|
|
||||||
## References:
|
## References:
|
||||||
|
|
||||||
@ -35,16 +41,22 @@ OpenShift/Kubernetes distribution like [OKD](https://www.okd.io/).
|
|||||||
|
|
||||||
## Versions
|
## Versions
|
||||||
|
|
||||||
If you have legacy version of `podman` (before 3.x) you might need to stick with legacy `podman-compose` `0.1.x` branch.
|
If you have legacy version of `podman` (before 3.1.0) you might need to stick with legacy `podman-compose` `0.1.x` branch.
|
||||||
The legacy branch 0.1.x uses mappings and workarounds to compensate for rootless limitations.
|
The legacy branch 0.1.x uses mappings and workarounds to compensate for rootless limitations.
|
||||||
|
|
||||||
Modern podman versions (>=3.4) do not have those limitations and thus you can use latest and stable 1.x branch.
|
Modern podman versions (>=3.4) do not have those limitations, and thus you can use latest and stable 1.x branch.
|
||||||
|
|
||||||
|
If you are upgrading from `podman-compose` version `0.1.x` then we no longer have global option `-t` to set mapping type
|
||||||
|
like `hostnet`. If you desire that behavior, pass it the standard way like `network_mode: host` in the YAML.
|
||||||
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Install latest stable version from PyPI:
|
### Pip
|
||||||
|
|
||||||
```
|
Install the latest stable version from PyPI:
|
||||||
|
|
||||||
|
```bash
|
||||||
pip3 install podman-compose
|
pip3 install podman-compose
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -52,37 +64,50 @@ pass `--user` to install inside regular user home without being root.
|
|||||||
|
|
||||||
Or latest development version from GitHub:
|
Or latest development version from GitHub:
|
||||||
|
|
||||||
```
|
```bash
|
||||||
pip3 install https://github.com/containers/podman-compose/archive/devel.tar.gz
|
pip3 install https://github.com/containers/podman-compose/archive/main.tar.gz
|
||||||
```
|
```
|
||||||
|
|
||||||
or
|
### Homebrew
|
||||||
|
|
||||||
|
```bash
|
||||||
|
brew install podman-compose
|
||||||
```
|
```
|
||||||
curl -o /usr/local/bin/podman-compose https://raw.githubusercontent.com/containers/podman-compose/devel/podman_compose.py
|
|
||||||
|
### Generate binary using docker/podman locally
|
||||||
|
This script will download the repo, generate the binary using [this Dockerfile](https://github.com/containers/podman-compose/blob/main/Dockerfile), and place the binary in the directory where you called this script.
|
||||||
|
```bash
|
||||||
|
sh -c "$(curl -sSL https://raw.githubusercontent.com/containers/podman-compose/main/scripts/download_and_build_podman-compose.sh)"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manual
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -o /usr/local/bin/podman-compose https://raw.githubusercontent.com/containers/podman-compose/main/podman_compose.py
|
||||||
chmod +x /usr/local/bin/podman-compose
|
chmod +x /usr/local/bin/podman-compose
|
||||||
```
|
```
|
||||||
|
|
||||||
or inside your home
|
or inside your home
|
||||||
|
|
||||||
```
|
```bash
|
||||||
curl -o ~/.local/bin/podman-compose https://raw.githubusercontent.com/containers/podman-compose/devel/podman_compose.py
|
curl -o ~/.local/bin/podman-compose https://raw.githubusercontent.com/containers/podman-compose/main/podman_compose.py
|
||||||
chmod +x ~/.local/bin/podman-compose
|
chmod +x ~/.local/bin/podman-compose
|
||||||
```
|
```
|
||||||
|
|
||||||
or install from Fedora (starting from f31) repositories:
|
or install from Fedora (starting from f31) repositories:
|
||||||
|
|
||||||
```
|
```bash
|
||||||
sudo dnf install podman-compose
|
sudo dnf install podman-compose
|
||||||
```
|
```
|
||||||
|
|
||||||
## Basic Usage
|
## Basic Usage
|
||||||
|
|
||||||
We have included fully functional sample stacks inside `examples/` directory.
|
We have included fully functional sample stacks inside `examples/` directory.
|
||||||
|
You can get more examples from [awesome-compose](https://github.com/docker/awesome-compose).
|
||||||
|
|
||||||
A quick example would be
|
A quick example would be
|
||||||
|
|
||||||
```
|
```bash
|
||||||
cd examples/busybox
|
cd examples/busybox
|
||||||
podman-compose --help
|
podman-compose --help
|
||||||
podman-compose up --help
|
podman-compose up --help
|
||||||
@ -99,12 +124,21 @@ which have
|
|||||||
- a django tasks
|
- a django tasks
|
||||||
|
|
||||||
|
|
||||||
When testing the `AWX3` example, if you got errors just wait for db migrations to end.
|
When testing the `AWX3` example, if you got errors, just wait for db migrations to end.
|
||||||
|
There is also AWX 17.1.0
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
|
|
||||||
Inside `tests/` directory we have many useless docker-compose stacks
|
Inside `tests/` directory we have many useless docker-compose stacks
|
||||||
that are meant to test as much cases as we can to make sure we are compatible
|
that are meant to test as many cases as we can to make sure we are compatible
|
||||||
|
|
||||||
|
### Unit tests with unittest
|
||||||
|
run a unittest with following command
|
||||||
|
|
||||||
|
```shell
|
||||||
|
python3 -m unittest discover tests/unit
|
||||||
|
```
|
||||||
|
|
||||||
|
# Contributing guide
|
||||||
|
|
||||||
|
If you are a user or a developer and want to contribute please check the [CONTRIBUTING](CONTRIBUTING.md) section
|
||||||
|
47
RELEASING.md
Normal file
47
RELEASING.md
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
Creating a release
|
||||||
|
==================
|
||||||
|
|
||||||
|
This file contains instructions for maintainers on how to release new versions of podman-compose.
|
||||||
|
|
||||||
|
Step 1: Initialize variables for subsequent steps
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
```
|
||||||
|
export VERSION=1.2.3
|
||||||
|
```
|
||||||
|
|
||||||
|
Step 2: Release notes PR
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
Open a new branch (e.g. `release`) and run the following:
|
||||||
|
|
||||||
|
```
|
||||||
|
./scripts/make_release_notes.sh $VERSION
|
||||||
|
```
|
||||||
|
|
||||||
|
This collects the release notes using the `towncrier` tool and then commits the result.
|
||||||
|
This step is done as a PR so that CI can check for spelling errors and similar issues.
|
||||||
|
|
||||||
|
Certain file names are not properly supported by the `towncrier` tool and it ignores them.
|
||||||
|
Check `newsfragments` directory for any forgotten release notes
|
||||||
|
|
||||||
|
Step 3: Merge the release notes PR
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
Step 4: Perform actual release
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
Pull the merge commit created on the `main` branch during the step 2.
|
||||||
|
Then run:
|
||||||
|
|
||||||
|
```
|
||||||
|
./scripts/make_release.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
This will create release commit, tag and push everything.
|
||||||
|
|
||||||
|
Step 5: Create a release on Github
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
The release notes must be added manually by drafting a release on the GitHub UI at
|
||||||
|
https://github.com/containers/podman-compose/releases.
|
411
completion/bash/podman-compose
Normal file
411
completion/bash/podman-compose
Normal file
@ -0,0 +1,411 @@
|
|||||||
|
# Naming convention:
|
||||||
|
# * _camelCase for function names
|
||||||
|
# * snake_case for variable names
|
||||||
|
|
||||||
|
# all functions will return 0 if they successfully complete the argument
|
||||||
|
# (or establish there is no need or no way to complete), and something
|
||||||
|
# other than 0 if that's not the case
|
||||||
|
|
||||||
|
# complete arguments to global options
|
||||||
|
_completeGlobalOptArgs() {
|
||||||
|
# arguments to options that take paths as arguments: complete paths
|
||||||
|
for el in ${path_arg_global_opts}; do
|
||||||
|
if [[ ${prev} == ${el} ]]; then
|
||||||
|
COMPREPLY=( $(compgen -f -- ${cur}) )
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# arguments to options that take generic arguments: don't complete
|
||||||
|
for el in ${generic_arg_global_opts}; do
|
||||||
|
if [[ ${prev} == ${el} ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# complete root subcommands and options
|
||||||
|
_completeRoot() {
|
||||||
|
# if we're completing an option
|
||||||
|
if [[ ${cur} == -* ]]; then
|
||||||
|
COMPREPLY=( $(compgen -W "${global_opts}" -- ${cur}) )
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
# complete root commands
|
||||||
|
COMPREPLY=( $(compgen -W "${root_commands}" -- ${cur}) )
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# complete names of Compose services
|
||||||
|
_completeServiceNames() {
|
||||||
|
# ideally we should complete service names,
|
||||||
|
# but parsing the compose spec file in the
|
||||||
|
# completion script is quite complex
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# complete commands to run inside containers
|
||||||
|
_completeCommand() {
|
||||||
|
# we would need to complete commands to run inside
|
||||||
|
# a container
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# complete the arguments for `podman-compose up` and return 0
|
||||||
|
_completeUpArgs() {
|
||||||
|
up_opts="${help_opts} -d --detach --no-color --quiet-pull --no-deps --force-recreate --always-recreate-deps --no-recreate --no-build --no-start --build --abort-on-container-exit -t --timeout -V --renew-anon-volumes --remove-orphans --scale --exit-code-from --pull --pull-always --build-arg --no-cache"
|
||||||
|
if [[ ${prev} == "--scale" || ${prev} == "-t" || ${prev} == "--timeout" ]]; then
|
||||||
|
return 0
|
||||||
|
elif [[ ${cur} == -* ]]; then
|
||||||
|
COMPREPLY=( $(compgen -W "${up_opts}" -- ${cur}) )
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_completeServiceNames
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
# complete the arguments for `podman-compose exec` and return 0
|
||||||
|
_completeExecArgs() {
|
||||||
|
exec_opts="${help_opts} -d --detach --privileged -u --user -T --index -e --env -w --workdir"
|
||||||
|
if [[ ${prev} == "-u" || ${prev} == "--user" || ${prev} == "--index" || ${prev} == "-e" || ${prev} == "--env" || ${prev} == "-w" || ${prev} == "--workdir" ]]; then
|
||||||
|
return 0
|
||||||
|
elif [[ ${cur} == -* ]]; then
|
||||||
|
COMPREPLY=( $(compgen -W "${exec_opts}" -- ${cur}) )
|
||||||
|
return 0
|
||||||
|
elif [[ ${comp_cword_adj} -eq 2 ]]; then
|
||||||
|
# complete service name
|
||||||
|
_completeServiceNames
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
elif [[ ${comp_cword_adj} -eq 3 ]]; then
|
||||||
|
_completeCommand
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# complete the arguments for `podman-compose down` and return 0
|
||||||
|
_completeDownArgs() {
|
||||||
|
down_opts="${help_opts} -v --volumes -t --timeout --remove-orphans"
|
||||||
|
if [[ ${prev} == "-t" || ${prev} == "--timeout" ]]; then
|
||||||
|
return 0
|
||||||
|
elif [[ ${cur} == -* ]]; then
|
||||||
|
COMPREPLY=( $(compgen -W "${down_opts}" -- ${cur}) )
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_completeServiceNames
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# complete the arguments for `podman-compose build` and return 0
|
||||||
|
_completeBuildArgs() {
|
||||||
|
build_opts="${help_opts} --pull --pull-always --build-arg --no-cache"
|
||||||
|
if [[ ${prev} == "--build-arg" ]]; then
|
||||||
|
return 0
|
||||||
|
elif [[ ${cur} == -* ]]; then
|
||||||
|
COMPREPLY=( $(compgen -W "${build_opts}" -- ${cur}) )
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_completeServiceNames
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# complete the arguments for `podman-compose logs` and return 0
|
||||||
|
_completeLogsArgs() {
|
||||||
|
logs_opts="${help_opts} -f --follow -l --latest -n --names --since -t --timestamps --tail --until"
|
||||||
|
if [[ ${prev} == "--since" || ${prev} == "--tail" || ${prev} == "--until" ]]; then
|
||||||
|
return 0
|
||||||
|
elif [[ ${cur} == -* ]]; then
|
||||||
|
COMPREPLY=( $(compgen -W "${logs_opts}" -- ${cur}) )
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_completeServiceNames
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# complete the arguments for `podman-compose ps` and return 0
|
||||||
|
_completePsArgs() {
|
||||||
|
ps_opts="${help_opts} -q --quiet"
|
||||||
|
if [[ ${cur} == -* ]]; then
|
||||||
|
COMPREPLY=( $(compgen -W "${ps_opts}" -- ${cur}) )
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# complete the arguments for `podman-compose pull` and return 0
|
||||||
|
_completePullArgs() {
|
||||||
|
pull_opts="${help_opts} --force-local"
|
||||||
|
if [[ ${cur} == -* ]]; then
|
||||||
|
COMPREPLY=( $(compgen -W "${pull_opts}" -- ${cur}) )
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# complete the arguments for `podman-compose push` and return 0
|
||||||
|
_completePushArgs() {
|
||||||
|
push_opts="${help_opts} --ignore-push-failures"
|
||||||
|
if [[ ${cur} == -* ]]; then
|
||||||
|
COMPREPLY=( $(compgen -W "${push_opts}" -- ${cur}) )
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_completeServiceNames
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# complete the arguments for `podman-compose restart` and return 0
|
||||||
|
_completeRestartArgs() {
|
||||||
|
restart_opts="${help_opts} -t --timeout"
|
||||||
|
if [[ ${prev} == "-t" || ${prev} == "--timeout" ]]; then
|
||||||
|
return 0
|
||||||
|
elif [[ ${cur} == -* ]]; then
|
||||||
|
COMPREPLY=( $(compgen -W "${restart_opts}" -- ${cur}) )
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_completeServiceNames
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# complete the arguments for `podman-compose stop` and return 0
|
||||||
|
_completeStopArgs() {
|
||||||
|
stop_opts="${help_opts} -t --timeout"
|
||||||
|
if [[ ${prev} == "-t" || ${prev} == "--timeout" ]]; then
|
||||||
|
return 0
|
||||||
|
elif [[ ${cur} == -* ]]; then
|
||||||
|
COMPREPLY=( $(compgen -W "${stop_opts}" -- ${cur}) )
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_completeServiceNames
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# complete the arguments for `podman-compose start` and return 0
|
||||||
|
_completeStartArgs() {
|
||||||
|
start_opts="${help_opts}"
|
||||||
|
if [[ ${cur} == -* ]]; then
|
||||||
|
COMPREPLY=( $(compgen -W "${start_opts}" -- ${cur}) )
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_completeServiceNames
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# complete the arguments for `podman-compose run` and return 0
|
||||||
|
_completeRunArgs() {
|
||||||
|
run_opts="${help_opts} -d --detach --privileged -u --user -T --index -e --env -w --workdir"
|
||||||
|
if [[ ${prev} == "-u" || ${prev} == "--user" || ${prev} == "--index" || ${prev} == "-e" || ${prev} == "--env" || ${prev} == "-w" || ${prev} == "--workdir" ]]; then
|
||||||
|
return 0
|
||||||
|
elif [[ ${cur} == -* ]]; then
|
||||||
|
COMPREPLY=( $(compgen -W "${run_opts}" -- ${cur}) )
|
||||||
|
return 0
|
||||||
|
elif [[ ${comp_cword_adj} -eq 2 ]]; then
|
||||||
|
# complete service name
|
||||||
|
_completeServiceNames
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
elif [[ ${comp_cword_adj} -eq 3 ]]; then
|
||||||
|
_completeCommand
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_podmanCompose() {
|
||||||
|
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||||
|
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||||
|
root_commands="help version pull push build up down ps run exec start stop restart logs"
|
||||||
|
|
||||||
|
# options to output help text (used as global and subcommand options)
|
||||||
|
help_opts="-h --help"
|
||||||
|
|
||||||
|
# global options that don't take additional arguments
|
||||||
|
basic_global_opts="${help_opts} -v --no-ansi --no-cleanup --dry-run"
|
||||||
|
|
||||||
|
# global options that take paths as arguments
|
||||||
|
path_arg_global_opts="-f --file --podman-path"
|
||||||
|
path_arg_global_opts_array=($arg_global_opts)
|
||||||
|
|
||||||
|
# global options that take arguments that are not files
|
||||||
|
generic_arg_global_opts="-p --project-name --podman-path --podman-args --podman-pull-args --podman-push-args --podman-build-args --podman-inspect-args --podman-run-args --podman-start-args --podman-stop-args --podman-rm-args --podman-volume-args"
|
||||||
|
generic_arg_global_opts_array=($generic_arg_global_opts)
|
||||||
|
|
||||||
|
# all global options that take arguments
|
||||||
|
arg_global_opts="${path_arg_global_opts} ${generic_arg_global_opts}"
|
||||||
|
arg_global_opts_array=($arg_global_opts)
|
||||||
|
|
||||||
|
# all global options
|
||||||
|
global_opts="${basic_global_opts} ${arg_global_opts}"
|
||||||
|
|
||||||
|
chosen_root_command=""
|
||||||
|
|
||||||
|
|
||||||
|
_completeGlobalOptArgs
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# computing comp_cword_adj, which thruthfully tells us how deep in the subcommands tree we are
|
||||||
|
# additionally, set the chosen_root_command if possible
|
||||||
|
comp_cword_adj=${COMP_CWORD}
|
||||||
|
if [[ ${COMP_CWORD} -ge 2 ]]; then
|
||||||
|
skip_next="no"
|
||||||
|
for el in ${COMP_WORDS[@]}; do
|
||||||
|
# if the user has asked for help text there's no need to complete further
|
||||||
|
if [[ ${el} == "-h" || ${el} == "--help" ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
if [[ ${skip_next} == "yes" ]]; then
|
||||||
|
let "comp_cword_adj--"
|
||||||
|
skip_next="no"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [[ ${el} == -* && ${el} != ${cur} ]]; then
|
||||||
|
let "comp_cword_adj--"
|
||||||
|
|
||||||
|
for opt in ${arg_global_opts_array[@]}; do
|
||||||
|
if [[ ${el} == ${opt} ]]; then
|
||||||
|
skip_next="yes"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
elif [[ ${el} != ${cur} && ${el} != ${COMP_WORDS[0]} && ${chosen_root_command} == "" ]]; then
|
||||||
|
chosen_root_command=${el}
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ${comp_cword_adj} -eq 1 ]]; then
|
||||||
|
_completeRoot
|
||||||
|
|
||||||
|
# Given that we check the value of comp_cword_adj outside
|
||||||
|
# of it, at the moment _completeRoot should always return
|
||||||
|
# 0, this is just here in case changes are made. The same
|
||||||
|
# will apply to similar functions below
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
case $chosen_root_command in
|
||||||
|
up)
|
||||||
|
_completeUpArgs
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
down)
|
||||||
|
_completeDownArgs
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
exec)
|
||||||
|
_completeExecArgs
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
build)
|
||||||
|
_completeBuildArgs
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
logs)
|
||||||
|
_completeLogsArgs
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
ps)
|
||||||
|
_completePsArgs
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
pull)
|
||||||
|
_completePullArgs
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
push)
|
||||||
|
_completePushArgs
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
restart)
|
||||||
|
_completeRestartArgs
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
start)
|
||||||
|
_completeStartArgs
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
_completeStopArgs
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
run)
|
||||||
|
_completeRunArgs
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
complete -F _podmanCompose podman-compose
|
33
docs/Changelog-1.1.0.md
Normal file
33
docs/Changelog-1.1.0.md
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
Version v1.1.0 (2024-04-17)
|
||||||
|
===========================
|
||||||
|
|
||||||
|
Bug fixes
|
||||||
|
---------
|
||||||
|
|
||||||
|
- Fixed support for values with equals sign in `-e` argument of `run` and `exec` commands.
|
||||||
|
- Fixed duplicate arguments being emitted in `stop` and `restart` commands.
|
||||||
|
- Removed extraneous debug output. `--verbose` flag has been added to preserve verbose output.
|
||||||
|
- Links aliases are now added to service aliases.
|
||||||
|
- Fixed image build process to use defined environmental variables.
|
||||||
|
- Empty list is now allowed to be `COMMAND` and `ENTRYPOINT`.
|
||||||
|
- Environment files are now resolved relative to current working directory.
|
||||||
|
- Exit code of container build is now preserved as return code of `build` command.
|
||||||
|
|
||||||
|
New features
|
||||||
|
------------
|
||||||
|
|
||||||
|
- Added support for `uidmap`, `gidmap`, `http_proxy` and `runtime` service configuration keys.
|
||||||
|
- Added support for `enable_ipv6` network configuration key.
|
||||||
|
- Added `--parallel` option to support parallel pulling and building of images.
|
||||||
|
- Implemented support for maps in `sysctls` container configuration key.
|
||||||
|
- Implemented `stats` command.
|
||||||
|
- Added `--no-normalize` flag to `config` command.
|
||||||
|
- Added support for `include` global configuration key.
|
||||||
|
- Added support for `build` command.
|
||||||
|
- Added support to start containers with multiple networks.
|
||||||
|
- Added support for `profile` argument.
|
||||||
|
- Added support for starting podman in existing network namespace.
|
||||||
|
- Added IPAM driver support.
|
||||||
|
- Added support for file secrets being passed to `podman build` via `--secret` argument.
|
||||||
|
- Added support for multiple networks with separately specified IP and MAC address.
|
||||||
|
- Added support for `service.build.ulimits` when building image.
|
40
docs/Changelog-1.2.0.md
Normal file
40
docs/Changelog-1.2.0.md
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
Version v1.2.0 (2024-06-26)
|
||||||
|
===========================
|
||||||
|
|
||||||
|
Bug fixes
|
||||||
|
---------
|
||||||
|
|
||||||
|
- Fixed handling of `--in-pod` argument. Previously it was hard to provide false value to it.
|
||||||
|
- podman-compose no longer creates pods when registering systemd unit.
|
||||||
|
- Fixed warning `RuntimeWarning: coroutine 'create_pods' was never awaited`
|
||||||
|
- Fixed error when setting up IPAM network with default driver.
|
||||||
|
- Fixed support for having list and dictionary `depends_on` sections in related compose files.
|
||||||
|
- Fixed logging of failed build message.
|
||||||
|
- Fixed support for multiple entries in `include` section.
|
||||||
|
- Fixed environment variable precedence order.
|
||||||
|
|
||||||
|
Changes
|
||||||
|
-------
|
||||||
|
|
||||||
|
- `x-podman` dictionary in container root has been migrated to `x-podman.*` fields in container root.
|
||||||
|
|
||||||
|
New features
|
||||||
|
------------
|
||||||
|
|
||||||
|
- Added support for `--publish` in `podman-compose run`.
|
||||||
|
- Added support for Podman external root filesystem management (`--rootfs` option).
|
||||||
|
- Added support for `podman-compose images` command.
|
||||||
|
- Added support for `env_file` being configured via dictionaries.
|
||||||
|
- Added support for enabling GPU access.
|
||||||
|
- Added support for selinux in verbose mount specification.
|
||||||
|
- Added support for `additional_contexts` section.
|
||||||
|
- Added support for multi-line environment files.
|
||||||
|
- Added support for passing contents of `podman-compose.yml` via stdin.
|
||||||
|
- Added support for specifying the value for `--in-pod` setting in `podman-compose.yml` file.
|
||||||
|
- Added support for environmental secrets.
|
||||||
|
|
||||||
|
Documentation
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- Added instructions on how to install podman-compose on Homebrew.
|
||||||
|
- Added explanation that netavark is an alternative to dnsname plugin
|
38
docs/Changelog-1.3.0.md
Normal file
38
docs/Changelog-1.3.0.md
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
Version 1.3.0 (2025-01-07)
|
||||||
|
==========================
|
||||||
|
|
||||||
|
Bug fixes
|
||||||
|
---------
|
||||||
|
|
||||||
|
- Fixed support for de-facto alternative `Dockerfile` names (e.g. `Containerfile`)
|
||||||
|
- Fixed a bug that caused attempts to create already existing pods multiple times.
|
||||||
|
- Fixed compatibility with docker-compose in how symlinks to docker-compose.yml are handled.
|
||||||
|
- Fixed freeze caused by too long log lines without a newline.
|
||||||
|
- Fixed support for `network_mode: none`.
|
||||||
|
- Improved error detection by rejecting service definitions that contain both `network_mode` and
|
||||||
|
`networks` keys, which is not allowed.
|
||||||
|
|
||||||
|
|
||||||
|
Features
|
||||||
|
--------
|
||||||
|
|
||||||
|
- Added support for build labels.
|
||||||
|
- Added support for "platform" property in the build command.
|
||||||
|
- Added support for "ssh" property in the build command.
|
||||||
|
- Added support for cache_from and cache_to fields in build section.
|
||||||
|
- Added support for honoring the condition in the depends_on section of the service, if stated.
|
||||||
|
- Added `x-podman.no_hosts` setting to pass `--no-hosts` to podman run
|
||||||
|
- Added support for compatibility with docker compose for default network behavior when no network
|
||||||
|
defined in service. This is controlled via `default_net_behavior_compat` feature flag.
|
||||||
|
- Added a way to get compatibility of default network names with docker compose.
|
||||||
|
This is selected by setting `default_net_name_compat: true` on `x-podman` global dictionary.
|
||||||
|
- Added support for the `device_cgroup_rules` property in services.
|
||||||
|
- Added support for removing networks in `podman-compose down`.
|
||||||
|
- Added support for network scoped service aliases.
|
||||||
|
- Added support for network level `mac_address` attribute.
|
||||||
|
- Added ability to substitute variables with the environment of the service.
|
||||||
|
|
||||||
|
Misc
|
||||||
|
----
|
||||||
|
|
||||||
|
- Declared compatibility with Python 3.13.
|
156
docs/Extensions.md
Normal file
156
docs/Extensions.md
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
# Podman specific extensions to the docker-compose format
|
||||||
|
|
||||||
|
Podman-compose supports the following extension to the docker-compose format. These extensions
|
||||||
|
are generally specified under fields with "x-podman" prefix in the compose file.
|
||||||
|
|
||||||
|
## Container management
|
||||||
|
|
||||||
|
The following extension keys are available under container configuration:
|
||||||
|
|
||||||
|
* `x-podman.uidmaps` - Run the container in a new user namespace using the supplied UID mapping.
|
||||||
|
|
||||||
|
* `x-podman.gidmaps` - Run the container in a new user namespace using the supplied GID mapping.
|
||||||
|
|
||||||
|
* `x-podman.rootfs` - Run the container without requiring any image management; the rootfs of the
|
||||||
|
container is assumed to be managed externally.
|
||||||
|
|
||||||
|
* `x-podman.no_hosts` - Run the container without creating /etc/hosts file
|
||||||
|
|
||||||
|
For example, the following docker-compose.yml allows running a podman container with externally managed rootfs.
|
||||||
|
```yml
|
||||||
|
version: "3"
|
||||||
|
services:
|
||||||
|
my_service:
|
||||||
|
command: ["/bin/busybox"]
|
||||||
|
x-podman.rootfs: "/path/to/rootfs"
|
||||||
|
```
|
||||||
|
|
||||||
|
For explanations of these extensions, please refer to the [Podman Documentation](https://docs.podman.io/).
|
||||||
|
|
||||||
|
|
||||||
|
## Per-network MAC-addresses
|
||||||
|
|
||||||
|
Generic docker-compose files support specification of the MAC address on the container level. If the
|
||||||
|
container has multiple network interfaces, the specified MAC address is applied to the first
|
||||||
|
specified network.
|
||||||
|
|
||||||
|
Podman-compose in addition supports the specification of MAC addresses on a per-network basis. This
|
||||||
|
is done by adding a `x-podman.mac_address` key to the network configuration in the container. The
|
||||||
|
value of the `x-podman.mac_address` key is the MAC address to be used for the network interface.
|
||||||
|
|
||||||
|
Note that the [compose spec](https://github.com/compose-spec/compose-spec/blob/main/05-services.md#mac_address)
|
||||||
|
now supports `mac_address` on the network level, so we recommend using
|
||||||
|
the standard `mac_address` key for setting the MAC address. The
|
||||||
|
`x-podman.mac_address` is still supported for backwards compatibility.
|
||||||
|
|
||||||
|
|
||||||
|
Specifying a MAC address for the container and for individual networks at the same time is not
|
||||||
|
supported.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
version: "3"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
net0:
|
||||||
|
driver: "bridge"
|
||||||
|
ipam:
|
||||||
|
config:
|
||||||
|
- subnet: "192.168.0.0/24"
|
||||||
|
net1:
|
||||||
|
driver: "bridge"
|
||||||
|
ipam:
|
||||||
|
config:
|
||||||
|
- subnet: "192.168.1.0/24"
|
||||||
|
|
||||||
|
services:
|
||||||
|
webserver
|
||||||
|
image: "busybox"
|
||||||
|
command: ["/bin/busybox", "httpd", "-f", "-h", "/etc", "-p", "8001"]
|
||||||
|
networks:
|
||||||
|
net0:
|
||||||
|
ipv4_address: "192.168.0.10"
|
||||||
|
x-podman.mac_address: "02:aa:aa:aa:aa:aa"
|
||||||
|
net1:
|
||||||
|
ipv4_address: "192.168.1.10"
|
||||||
|
mac_address: "02:bb:bb:bb:bb:bb" # mac_address is supported
|
||||||
|
```
|
||||||
|
|
||||||
|
## Podman-specific network modes
|
||||||
|
|
||||||
|
Generic docker-compose supports the following values for `network-mode` for a container:
|
||||||
|
|
||||||
|
- `bridge`
|
||||||
|
- `host`
|
||||||
|
- `none`
|
||||||
|
- `service`
|
||||||
|
- `container`
|
||||||
|
|
||||||
|
In addition, podman-compose supports the following podman-specific values for `network-mode`:
|
||||||
|
|
||||||
|
- `slirp4netns[:<options>,...]`
|
||||||
|
- `ns:<options>`
|
||||||
|
- `pasta[:<options>,...]`
|
||||||
|
- `private`
|
||||||
|
|
||||||
|
The options to the network modes are passed to the `--network` option of the `podman create` command
|
||||||
|
as-is.
|
||||||
|
|
||||||
|
|
||||||
|
## Compatibility of default network names between docker-compose and podman-compose
|
||||||
|
|
||||||
|
Current versions of podman-compose may produce different default external network names than
|
||||||
|
docker-compose under certain conditions. Specifically, docker-compose removes dashes (`-` character)
|
||||||
|
from project name.
|
||||||
|
|
||||||
|
To enable compatibility between docker-compose and podman-compose, specify
|
||||||
|
`default_net_name_compat: true` under global `x-podman` key:
|
||||||
|
|
||||||
|
```
|
||||||
|
x-podman:
|
||||||
|
default_net_name_compat: true
|
||||||
|
```
|
||||||
|
|
||||||
|
By default `default_net_name_compat` is `false`. This will change to `true` at some point and the
|
||||||
|
setting will be removed.
|
||||||
|
|
||||||
|
## Compatibility of default network behavior between docker-compose and podman-compose
|
||||||
|
|
||||||
|
When there is no network defined (neither network-mode nor networks) in service,
|
||||||
|
The behavior of default network in docker-compose and podman-compose are different.
|
||||||
|
|
||||||
|
| Top-level networks | podman-compose | docker-compose |
|
||||||
|
| ------------------------------ | -------------------------- | -------------- |
|
||||||
|
| No networks | default | default |
|
||||||
|
| One network named net0 | net0 | default |
|
||||||
|
| Two networks named net0, net1 | podman(`--network=bridge`) | default |
|
||||||
|
| Contains network named default | default | default |
|
||||||
|
|
||||||
|
To enable compatibility between docker-compose and podman-compose, specify
|
||||||
|
`default_net_behavior_compat: true` under global `x-podman` key:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
x-podman:
|
||||||
|
default_net_behavior_compat: true
|
||||||
|
```
|
||||||
|
|
||||||
|
## Custom pods management
|
||||||
|
|
||||||
|
Podman-compose can have containers in pods. This can be controlled by extension key x-podman in_pod.
|
||||||
|
It allows providing custom value for --in-pod and is especially relevant when --userns has to be set.
|
||||||
|
|
||||||
|
For example, the following docker-compose.yml allows using userns_mode by overriding the default
|
||||||
|
value of --in-pod (unless it was specifically provided by "--in-pod=True" in command line interface).
|
||||||
|
```yml
|
||||||
|
version: "3"
|
||||||
|
services:
|
||||||
|
cont:
|
||||||
|
image: nopush/podman-compose-test
|
||||||
|
userns_mode: keep-id:uid=1000
|
||||||
|
command: ["dumb-init", "/bin/busybox", "httpd", "-f", "-p", "8080"]
|
||||||
|
|
||||||
|
x-podman:
|
||||||
|
in_pod: false
|
||||||
|
```
|
37
examples/awx17/README.md
Normal file
37
examples/awx17/README.md
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# AWX Compose
|
||||||
|
|
||||||
|
the directory roles is taken from [here](https://github.com/ansible/awx/tree/17.1.0/installer/roles/local_docker)
|
||||||
|
|
||||||
|
also look at https://github.com/ansible/awx/tree/17.1.0/tools/docker-compose
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir deploy awx17
|
||||||
|
ansible localhost \
|
||||||
|
-e host_port=8080 \
|
||||||
|
-e awx_secret_key='awx,secret.123' \
|
||||||
|
-e secret_key='awx,secret.123' \
|
||||||
|
-e admin_user='admin' \
|
||||||
|
-e admin_password='admin' \
|
||||||
|
-e pg_password='awx,123.' \
|
||||||
|
-e pg_username='awx' \
|
||||||
|
-e pg_database='awx' \
|
||||||
|
-e pg_port='5432' \
|
||||||
|
-e redis_image="docker.io/library/redis:6-alpine" \
|
||||||
|
-e postgres_data_dir="./data/pg" \
|
||||||
|
-e compose_start_containers=false \
|
||||||
|
-e dockerhub_base='docker.io/ansible' \
|
||||||
|
-e awx_image='docker.io/ansible/awx' \
|
||||||
|
-e awx_version='17.1.0' \
|
||||||
|
-e dockerhub_version='17.1.0' \
|
||||||
|
-e docker_deploy_base_path=$PWD/deploy \
|
||||||
|
-e docker_compose_dir=$PWD/awx17 \
|
||||||
|
-e awx_task_hostname=awx \
|
||||||
|
-e awx_web_hostname=awxweb \
|
||||||
|
-m include_role -a name=local_docker
|
||||||
|
cp awx17/docker-compose.yml awx17/docker-compose.yml.orig
|
||||||
|
sed -i -re "s#- \"$PWD/awx17/(.*):/#- \"./\1:/#" awx17/docker-compose.yml
|
||||||
|
cd awx17
|
||||||
|
podman-compose run --rm --service-ports task awx-manage migrate --no-input
|
||||||
|
podman-compose up -d
|
||||||
|
```
|
||||||
|
|
11
examples/awx17/roles/local_docker/defaults/main.yml
Normal file
11
examples/awx17/roles/local_docker/defaults/main.yml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
dockerhub_version: "{{ lookup('file', playbook_dir + '/../VERSION') }}"
|
||||||
|
|
||||||
|
awx_image: "awx"
|
||||||
|
redis_image: "redis"
|
||||||
|
|
||||||
|
postgresql_version: "12"
|
||||||
|
postgresql_image: "postgres:{{postgresql_version}}"
|
||||||
|
|
||||||
|
compose_start_containers: true
|
||||||
|
upgrade_postgres: false
|
74
examples/awx17/roles/local_docker/tasks/compose.yml
Normal file
74
examples/awx17/roles/local_docker/tasks/compose.yml
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
---
|
||||||
|
- name: Create {{ docker_compose_dir }} directory
|
||||||
|
file:
|
||||||
|
path: "{{ docker_compose_dir }}"
|
||||||
|
state: directory
|
||||||
|
|
||||||
|
- name: Create Redis socket directory
|
||||||
|
file:
|
||||||
|
path: "{{ docker_compose_dir }}/redis_socket"
|
||||||
|
state: directory
|
||||||
|
mode: 0777
|
||||||
|
|
||||||
|
- name: Create Docker Compose Configuration
|
||||||
|
template:
|
||||||
|
src: "{{ item.file }}.j2"
|
||||||
|
dest: "{{ docker_compose_dir }}/{{ item.file }}"
|
||||||
|
mode: "{{ item.mode }}"
|
||||||
|
loop:
|
||||||
|
- file: environment.sh
|
||||||
|
mode: "0600"
|
||||||
|
- file: credentials.py
|
||||||
|
mode: "0600"
|
||||||
|
- file: docker-compose.yml
|
||||||
|
mode: "0600"
|
||||||
|
- file: nginx.conf
|
||||||
|
mode: "0600"
|
||||||
|
- file: redis.conf
|
||||||
|
mode: "0664"
|
||||||
|
register: awx_compose_config
|
||||||
|
|
||||||
|
- name: Render SECRET_KEY file
|
||||||
|
copy:
|
||||||
|
content: "{{ secret_key }}"
|
||||||
|
dest: "{{ docker_compose_dir }}/SECRET_KEY"
|
||||||
|
mode: 0600
|
||||||
|
register: awx_secret_key
|
||||||
|
|
||||||
|
- block:
|
||||||
|
- name: Remove AWX containers before migrating postgres so that the old postgres container does not get used
|
||||||
|
docker_compose:
|
||||||
|
project_src: "{{ docker_compose_dir }}"
|
||||||
|
state: absent
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Run migrations in task container
|
||||||
|
shell: docker-compose run --rm --service-ports task awx-manage migrate --no-input
|
||||||
|
args:
|
||||||
|
chdir: "{{ docker_compose_dir }}"
|
||||||
|
|
||||||
|
- name: Start the containers
|
||||||
|
docker_compose:
|
||||||
|
project_src: "{{ docker_compose_dir }}"
|
||||||
|
restarted: "{{ awx_compose_config is changed or awx_secret_key is changed }}"
|
||||||
|
register: awx_compose_start
|
||||||
|
|
||||||
|
- name: Update CA trust in awx_web container
|
||||||
|
command: docker exec awx_web '/usr/bin/update-ca-trust'
|
||||||
|
when: awx_compose_config.changed or awx_compose_start.changed
|
||||||
|
|
||||||
|
- name: Update CA trust in awx_task container
|
||||||
|
command: docker exec awx_task '/usr/bin/update-ca-trust'
|
||||||
|
when: awx_compose_config.changed or awx_compose_start.changed
|
||||||
|
|
||||||
|
- name: Wait for launch script to create user
|
||||||
|
wait_for:
|
||||||
|
timeout: 10
|
||||||
|
delegate_to: localhost
|
||||||
|
|
||||||
|
- name: Create Preload data
|
||||||
|
command: docker exec awx_task bash -c "/usr/bin/awx-manage create_preload_data"
|
||||||
|
when: create_preload_data|bool
|
||||||
|
register: cdo
|
||||||
|
changed_when: "'added' in cdo.stdout"
|
||||||
|
when: compose_start_containers|bool
|
15
examples/awx17/roles/local_docker/tasks/main.yml
Normal file
15
examples/awx17/roles/local_docker/tasks/main.yml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
- name: Generate broadcast websocket secret
|
||||||
|
set_fact:
|
||||||
|
broadcast_websocket_secret: "{{ lookup('password', '/dev/null length=128') }}"
|
||||||
|
run_once: true
|
||||||
|
no_log: true
|
||||||
|
when: broadcast_websocket_secret is not defined
|
||||||
|
|
||||||
|
- import_tasks: upgrade_postgres.yml
|
||||||
|
when:
|
||||||
|
- postgres_data_dir is defined
|
||||||
|
- pg_hostname is not defined
|
||||||
|
|
||||||
|
- import_tasks: set_image.yml
|
||||||
|
- import_tasks: compose.yml
|
46
examples/awx17/roles/local_docker/tasks/set_image.yml
Normal file
46
examples/awx17/roles/local_docker/tasks/set_image.yml
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
---
|
||||||
|
- name: Manage AWX Container Images
|
||||||
|
block:
|
||||||
|
- name: Export Docker awx image if it isn't local and there isn't a registry defined
|
||||||
|
docker_image:
|
||||||
|
name: "{{ awx_image }}"
|
||||||
|
tag: "{{ awx_version }}"
|
||||||
|
archive_path: "{{ awx_local_base_config_path|default('/tmp') }}/{{ awx_image }}_{{ awx_version }}.tar"
|
||||||
|
when: inventory_hostname != "localhost" and docker_registry is not defined
|
||||||
|
delegate_to: localhost
|
||||||
|
|
||||||
|
- name: Set docker base path
|
||||||
|
set_fact:
|
||||||
|
docker_deploy_base_path: "{{ awx_base_path|default('/tmp') }}/docker_deploy"
|
||||||
|
when: ansible_connection != "local" and docker_registry is not defined
|
||||||
|
|
||||||
|
- name: Ensure directory exists
|
||||||
|
file:
|
||||||
|
path: "{{ docker_deploy_base_path }}"
|
||||||
|
state: directory
|
||||||
|
when: ansible_connection != "local" and docker_registry is not defined
|
||||||
|
|
||||||
|
- name: Copy awx image to docker execution
|
||||||
|
copy:
|
||||||
|
src: "{{ awx_local_base_config_path|default('/tmp') }}/{{ awx_image }}_{{ awx_version }}.tar"
|
||||||
|
dest: "{{ docker_deploy_base_path }}/{{ awx_image }}_{{ awx_version }}.tar"
|
||||||
|
when: ansible_connection != "local" and docker_registry is not defined
|
||||||
|
|
||||||
|
- name: Load awx image
|
||||||
|
docker_image:
|
||||||
|
name: "{{ awx_image }}"
|
||||||
|
tag: "{{ awx_version }}"
|
||||||
|
load_path: "{{ docker_deploy_base_path }}/{{ awx_image }}_{{ awx_version }}.tar"
|
||||||
|
timeout: 300
|
||||||
|
when: ansible_connection != "local" and docker_registry is not defined
|
||||||
|
|
||||||
|
- name: Set full image path for local install
|
||||||
|
set_fact:
|
||||||
|
awx_docker_actual_image: "{{ awx_image }}:{{ awx_version }}"
|
||||||
|
when: docker_registry is not defined
|
||||||
|
when: dockerhub_base is not defined
|
||||||
|
|
||||||
|
- name: Set DockerHub Image Paths
|
||||||
|
set_fact:
|
||||||
|
awx_docker_actual_image: "{{ dockerhub_base }}/awx:{{ dockerhub_version }}"
|
||||||
|
when: dockerhub_base is defined
|
64
examples/awx17/roles/local_docker/tasks/upgrade_postgres.yml
Normal file
64
examples/awx17/roles/local_docker/tasks/upgrade_postgres.yml
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
- name: Create {{ postgres_data_dir }} directory
|
||||||
|
file:
|
||||||
|
path: "{{ postgres_data_dir }}"
|
||||||
|
state: directory
|
||||||
|
|
||||||
|
- name: Get full path of postgres data dir
|
||||||
|
shell: "echo {{ postgres_data_dir }}"
|
||||||
|
register: fq_postgres_data_dir
|
||||||
|
|
||||||
|
- name: Register temporary docker container
|
||||||
|
set_fact:
|
||||||
|
container_command: "docker run --rm -v '{{ fq_postgres_data_dir.stdout }}:/var/lib/postgresql' centos:8 bash -c "
|
||||||
|
|
||||||
|
- name: Check for existing Postgres data (run from inside the container for access to file)
|
||||||
|
shell:
|
||||||
|
cmd: |
|
||||||
|
{{ container_command }} "[[ -f /var/lib/postgresql/10/data/PG_VERSION ]] && echo 'exists'"
|
||||||
|
register: pg_version_file
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Record Postgres version
|
||||||
|
shell: |
|
||||||
|
{{ container_command }} "cat /var/lib/postgresql/10/data/PG_VERSION"
|
||||||
|
register: old_pg_version
|
||||||
|
when: pg_version_file is defined and pg_version_file.stdout == 'exists'
|
||||||
|
|
||||||
|
- name: Determine whether to upgrade postgres
|
||||||
|
set_fact:
|
||||||
|
upgrade_postgres: "{{ old_pg_version.stdout == '10' }}"
|
||||||
|
when: old_pg_version.changed
|
||||||
|
|
||||||
|
- name: Set up new postgres paths pre-upgrade
|
||||||
|
shell: |
|
||||||
|
{{ container_command }} "mkdir -p /var/lib/postgresql/12/data/"
|
||||||
|
when: upgrade_postgres | bool
|
||||||
|
|
||||||
|
- name: Stop AWX before upgrading postgres
|
||||||
|
docker_compose:
|
||||||
|
project_src: "{{ docker_compose_dir }}"
|
||||||
|
stopped: true
|
||||||
|
when: upgrade_postgres | bool
|
||||||
|
|
||||||
|
- name: Upgrade Postgres
|
||||||
|
shell: |
|
||||||
|
docker run --rm \
|
||||||
|
-v {{ postgres_data_dir }}/10/data:/var/lib/postgresql/10/data \
|
||||||
|
-v {{ postgres_data_dir }}/12/data:/var/lib/postgresql/12/data \
|
||||||
|
-e PGUSER={{ pg_username }} -e POSTGRES_INITDB_ARGS="-U {{ pg_username }}" \
|
||||||
|
tianon/postgres-upgrade:10-to-12 --username={{ pg_username }}
|
||||||
|
when: upgrade_postgres | bool
|
||||||
|
|
||||||
|
- name: Copy old pg_hba.conf
|
||||||
|
shell: |
|
||||||
|
{{ container_command }} "cp /var/lib/postgresql/10/data/pg_hba.conf /var/lib/postgresql/12/data/pg_hba.conf"
|
||||||
|
when: upgrade_postgres | bool
|
||||||
|
|
||||||
|
- name: Remove old data directory
|
||||||
|
shell: |
|
||||||
|
{{ container_command }} "rm -rf /var/lib/postgresql/10/data"
|
||||||
|
when:
|
||||||
|
- upgrade_postgres | bool
|
||||||
|
- compose_start_containers|bool
|
@ -0,0 +1,13 @@
|
|||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ATOMIC_REQUESTS': True,
|
||||||
|
'ENGINE': 'django.db.backends.postgresql',
|
||||||
|
'NAME': "{{ pg_database }}",
|
||||||
|
'USER': "{{ pg_username }}",
|
||||||
|
'PASSWORD': "{{ pg_password }}",
|
||||||
|
'HOST': "{{ pg_hostname | default('postgres') }}",
|
||||||
|
'PORT': "{{ pg_port }}",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BROADCAST_WEBSOCKET_SECRET = "{{ broadcast_websocket_secret | b64encode }}"
|
@ -0,0 +1,208 @@
|
|||||||
|
#jinja2: lstrip_blocks: True
|
||||||
|
version: '2'
|
||||||
|
services:
|
||||||
|
|
||||||
|
web:
|
||||||
|
image: {{ awx_docker_actual_image }}
|
||||||
|
container_name: awx_web
|
||||||
|
depends_on:
|
||||||
|
- redis
|
||||||
|
{% if pg_hostname is not defined %}
|
||||||
|
- postgres
|
||||||
|
{% endif %}
|
||||||
|
{% if (host_port is defined) or (host_port_ssl is defined) %}
|
||||||
|
ports:
|
||||||
|
{% if (host_port_ssl is defined) and (ssl_certificate is defined) %}
|
||||||
|
- "{{ host_port_ssl }}:8053"
|
||||||
|
{% endif %}
|
||||||
|
{% if host_port is defined %}
|
||||||
|
- "{{ host_port }}:8052"
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
hostname: {{ awx_web_hostname }}
|
||||||
|
user: root
|
||||||
|
restart: unless-stopped
|
||||||
|
{% if (awx_web_container_labels is defined) and (',' in awx_web_container_labels) %}
|
||||||
|
{% set awx_web_container_labels_list = awx_web_container_labels.split(',') %}
|
||||||
|
labels:
|
||||||
|
{% for awx_web_container_label in awx_web_container_labels_list %}
|
||||||
|
- {{ awx_web_container_label }}
|
||||||
|
{% endfor %}
|
||||||
|
{% elif awx_web_container_labels is defined %}
|
||||||
|
labels:
|
||||||
|
- {{ awx_web_container_labels }}
|
||||||
|
{% endif %}
|
||||||
|
volumes:
|
||||||
|
- supervisor-socket:/var/run/supervisor
|
||||||
|
- rsyslog-socket:/var/run/awx-rsyslog/
|
||||||
|
- rsyslog-config:/var/lib/awx/rsyslog/
|
||||||
|
- "{{ docker_compose_dir }}/SECRET_KEY:/etc/tower/SECRET_KEY"
|
||||||
|
- "{{ docker_compose_dir }}/environment.sh:/etc/tower/conf.d/environment.sh"
|
||||||
|
- "{{ docker_compose_dir }}/credentials.py:/etc/tower/conf.d/credentials.py"
|
||||||
|
- "{{ docker_compose_dir }}/nginx.conf:/etc/nginx/nginx.conf:ro"
|
||||||
|
- "{{ docker_compose_dir }}/redis_socket:/var/run/redis/:rw"
|
||||||
|
{% if project_data_dir is defined %}
|
||||||
|
- "{{ project_data_dir +':/var/lib/awx/projects:rw' }}"
|
||||||
|
{% endif %}
|
||||||
|
{% if custom_venv_dir is defined %}
|
||||||
|
- "{{ custom_venv_dir +':'+ custom_venv_dir +':rw' }}"
|
||||||
|
{% endif %}
|
||||||
|
{% if ca_trust_dir is defined %}
|
||||||
|
- "{{ ca_trust_dir +':/etc/pki/ca-trust/source/anchors:ro' }}"
|
||||||
|
{% endif %}
|
||||||
|
{% if (ssl_certificate is defined) and (ssl_certificate_key is defined) %}
|
||||||
|
- "{{ ssl_certificate +':/etc/nginx/awxweb.pem:ro' }}"
|
||||||
|
- "{{ ssl_certificate_key +':/etc/nginx/awxweb_key.pem:ro' }}"
|
||||||
|
{% elif (ssl_certificate is defined) and (ssl_certificate_key is not defined) %}
|
||||||
|
- "{{ ssl_certificate +':/etc/nginx/awxweb.pem:ro' }}"
|
||||||
|
{% endif %}
|
||||||
|
{% if (awx_container_search_domains is defined) and (',' in awx_container_search_domains) %}
|
||||||
|
{% set awx_container_search_domains_list = awx_container_search_domains.split(',') %}
|
||||||
|
dns_search:
|
||||||
|
{% for awx_container_search_domain in awx_container_search_domains_list %}
|
||||||
|
- {{ awx_container_search_domain }}
|
||||||
|
{% endfor %}
|
||||||
|
{% elif awx_container_search_domains is defined %}
|
||||||
|
dns_search: "{{ awx_container_search_domains }}"
|
||||||
|
{% endif %}
|
||||||
|
{% if (awx_alternate_dns_servers is defined) and (',' in awx_alternate_dns_servers) %}
|
||||||
|
{% set awx_alternate_dns_servers_list = awx_alternate_dns_servers.split(',') %}
|
||||||
|
dns:
|
||||||
|
{% for awx_alternate_dns_server in awx_alternate_dns_servers_list %}
|
||||||
|
- {{ awx_alternate_dns_server }}
|
||||||
|
{% endfor %}
|
||||||
|
{% elif awx_alternate_dns_servers is defined %}
|
||||||
|
dns: "{{ awx_alternate_dns_servers }}"
|
||||||
|
{% endif %}
|
||||||
|
{% if (docker_compose_extra_hosts is defined) and (':' in docker_compose_extra_hosts) %}
|
||||||
|
{% set docker_compose_extra_hosts_list = docker_compose_extra_hosts.split(',') %}
|
||||||
|
extra_hosts:
|
||||||
|
{% for docker_compose_extra_host in docker_compose_extra_hosts_list %}
|
||||||
|
- "{{ docker_compose_extra_host }}"
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
environment:
|
||||||
|
http_proxy: {{ http_proxy | default('') }}
|
||||||
|
https_proxy: {{ https_proxy | default('') }}
|
||||||
|
no_proxy: {{ no_proxy | default('') }}
|
||||||
|
{% if docker_logger is defined %}
|
||||||
|
logging:
|
||||||
|
driver: {{ docker_logger }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
task:
|
||||||
|
image: {{ awx_docker_actual_image }}
|
||||||
|
container_name: awx_task
|
||||||
|
depends_on:
|
||||||
|
- redis
|
||||||
|
- web
|
||||||
|
{% if pg_hostname is not defined %}
|
||||||
|
- postgres
|
||||||
|
{% endif %}
|
||||||
|
command: /usr/bin/launch_awx_task.sh
|
||||||
|
hostname: {{ awx_task_hostname }}
|
||||||
|
user: root
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- supervisor-socket:/var/run/supervisor
|
||||||
|
- rsyslog-socket:/var/run/awx-rsyslog/
|
||||||
|
- rsyslog-config:/var/lib/awx/rsyslog/
|
||||||
|
- "{{ docker_compose_dir }}/SECRET_KEY:/etc/tower/SECRET_KEY"
|
||||||
|
- "{{ docker_compose_dir }}/environment.sh:/etc/tower/conf.d/environment.sh"
|
||||||
|
- "{{ docker_compose_dir }}/credentials.py:/etc/tower/conf.d/credentials.py"
|
||||||
|
- "{{ docker_compose_dir }}/redis_socket:/var/run/redis/:rw"
|
||||||
|
{% if project_data_dir is defined %}
|
||||||
|
- "{{ project_data_dir +':/var/lib/awx/projects:rw' }}"
|
||||||
|
{% endif %}
|
||||||
|
{% if custom_venv_dir is defined %}
|
||||||
|
- "{{ custom_venv_dir +':'+ custom_venv_dir +':rw' }}"
|
||||||
|
{% endif %}
|
||||||
|
{% if ca_trust_dir is defined %}
|
||||||
|
- "{{ ca_trust_dir +':/etc/pki/ca-trust/source/anchors:ro' }}"
|
||||||
|
{% endif %}
|
||||||
|
{% if ssl_certificate is defined %}
|
||||||
|
- "{{ ssl_certificate +':/etc/nginx/awxweb.pem:ro' }}"
|
||||||
|
{% endif %}
|
||||||
|
{% if (awx_container_search_domains is defined) and (',' in awx_container_search_domains) %}
|
||||||
|
{% set awx_container_search_domains_list = awx_container_search_domains.split(',') %}
|
||||||
|
dns_search:
|
||||||
|
{% for awx_container_search_domain in awx_container_search_domains_list %}
|
||||||
|
- {{ awx_container_search_domain }}
|
||||||
|
{% endfor %}
|
||||||
|
{% elif awx_container_search_domains is defined %}
|
||||||
|
dns_search: "{{ awx_container_search_domains }}"
|
||||||
|
{% endif %}
|
||||||
|
{% if (awx_alternate_dns_servers is defined) and (',' in awx_alternate_dns_servers) %}
|
||||||
|
{% set awx_alternate_dns_servers_list = awx_alternate_dns_servers.split(',') %}
|
||||||
|
dns:
|
||||||
|
{% for awx_alternate_dns_server in awx_alternate_dns_servers_list %}
|
||||||
|
- {{ awx_alternate_dns_server }}
|
||||||
|
{% endfor %}
|
||||||
|
{% elif awx_alternate_dns_servers is defined %}
|
||||||
|
dns: "{{ awx_alternate_dns_servers }}"
|
||||||
|
{% endif %}
|
||||||
|
{% if (docker_compose_extra_hosts is defined) and (':' in docker_compose_extra_hosts) %}
|
||||||
|
{% set docker_compose_extra_hosts_list = docker_compose_extra_hosts.split(',') %}
|
||||||
|
extra_hosts:
|
||||||
|
{% for docker_compose_extra_host in docker_compose_extra_hosts_list %}
|
||||||
|
- "{{ docker_compose_extra_host }}"
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
environment:
|
||||||
|
AWX_SKIP_MIGRATIONS: "1"
|
||||||
|
http_proxy: {{ http_proxy | default('') }}
|
||||||
|
https_proxy: {{ https_proxy | default('') }}
|
||||||
|
no_proxy: {{ no_proxy | default('') }}
|
||||||
|
SUPERVISOR_WEB_CONFIG_PATH: '/etc/supervisord.conf'
|
||||||
|
|
||||||
|
redis:
|
||||||
|
image: {{ redis_image }}
|
||||||
|
container_name: awx_redis
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
http_proxy: {{ http_proxy | default('') }}
|
||||||
|
https_proxy: {{ https_proxy | default('') }}
|
||||||
|
no_proxy: {{ no_proxy | default('') }}
|
||||||
|
command: ["/usr/local/etc/redis/redis.conf"]
|
||||||
|
volumes:
|
||||||
|
- "{{ docker_compose_dir }}/redis.conf:/usr/local/etc/redis/redis.conf:ro"
|
||||||
|
- "{{ docker_compose_dir }}/redis_socket:/var/run/redis/:rw"
|
||||||
|
{% if docker_logger is defined %}
|
||||||
|
logging:
|
||||||
|
driver: {{ docker_logger }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if pg_hostname is not defined %}
|
||||||
|
postgres:
|
||||||
|
image: {{ postgresql_image }}
|
||||||
|
container_name: awx_postgres
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- "{{ postgres_data_dir }}/12/data/:/var/lib/postgresql/data:Z"
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: {{ pg_username }}
|
||||||
|
POSTGRES_PASSWORD: {{ pg_password }}
|
||||||
|
POSTGRES_DB: {{ pg_database }}
|
||||||
|
http_proxy: {{ http_proxy | default('') }}
|
||||||
|
https_proxy: {{ https_proxy | default('') }}
|
||||||
|
no_proxy: {{ no_proxy | default('') }}
|
||||||
|
{% if docker_logger is defined %}
|
||||||
|
logging:
|
||||||
|
driver: {{ docker_logger }}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if docker_compose_subnet is defined %}
|
||||||
|
networks:
|
||||||
|
default:
|
||||||
|
driver: bridge
|
||||||
|
ipam:
|
||||||
|
driver: default
|
||||||
|
config:
|
||||||
|
- subnet: {{ docker_compose_subnet }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
supervisor-socket:
|
||||||
|
rsyslog-socket:
|
||||||
|
rsyslog-config:
|
@ -0,0 +1,10 @@
|
|||||||
|
DATABASE_USER={{ pg_username|quote }}
|
||||||
|
DATABASE_NAME={{ pg_database|quote }}
|
||||||
|
DATABASE_HOST={{ pg_hostname|default('postgres')|quote }}
|
||||||
|
DATABASE_PORT={{ pg_port|default('5432')|quote }}
|
||||||
|
DATABASE_PASSWORD={{ pg_password|default('awxpass')|quote }}
|
||||||
|
{% if pg_admin_password is defined %}
|
||||||
|
DATABASE_ADMIN_PASSWORD={{ pg_admin_password|quote }}
|
||||||
|
{% endif %}
|
||||||
|
AWX_ADMIN_USER={{ admin_user|quote }}
|
||||||
|
AWX_ADMIN_PASSWORD={{ admin_password|quote }}
|
122
examples/awx17/roles/local_docker/templates/nginx.conf.j2
Normal file
122
examples/awx17/roles/local_docker/templates/nginx.conf.j2
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
#user awx;
|
||||||
|
|
||||||
|
worker_processes 1;
|
||||||
|
|
||||||
|
pid /tmp/nginx.pid;
|
||||||
|
|
||||||
|
events {
|
||||||
|
worker_connections 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
include /etc/nginx/mime.types;
|
||||||
|
default_type application/octet-stream;
|
||||||
|
server_tokens off;
|
||||||
|
|
||||||
|
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||||
|
'$status $body_bytes_sent "$http_referer" '
|
||||||
|
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||||
|
|
||||||
|
access_log /dev/stdout main;
|
||||||
|
|
||||||
|
map $http_upgrade $connection_upgrade {
|
||||||
|
default upgrade;
|
||||||
|
'' close;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendfile on;
|
||||||
|
#tcp_nopush on;
|
||||||
|
#gzip on;
|
||||||
|
|
||||||
|
upstream uwsgi {
|
||||||
|
server 127.0.0.1:8050;
|
||||||
|
}
|
||||||
|
|
||||||
|
upstream daphne {
|
||||||
|
server 127.0.0.1:8051;
|
||||||
|
}
|
||||||
|
|
||||||
|
{% if ssl_certificate is defined %}
|
||||||
|
server {
|
||||||
|
listen 8052 default_server;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
# Redirect all HTTP links to the matching HTTPS page
|
||||||
|
return 301 https://$host$request_uri;
|
||||||
|
}
|
||||||
|
{%endif %}
|
||||||
|
|
||||||
|
server {
|
||||||
|
{% if (ssl_certificate is defined) and (ssl_certificate_key is defined) %}
|
||||||
|
listen 8053 ssl;
|
||||||
|
|
||||||
|
ssl_certificate /etc/nginx/awxweb.pem;
|
||||||
|
ssl_certificate_key /etc/nginx/awxweb_key.pem;
|
||||||
|
{% elif (ssl_certificate is defined) and (ssl_certificate_key is not defined) %}
|
||||||
|
listen 8053 ssl;
|
||||||
|
|
||||||
|
ssl_certificate /etc/nginx/awxweb.pem;
|
||||||
|
ssl_certificate_key /etc/nginx/awxweb.pem;
|
||||||
|
{% else %}
|
||||||
|
listen 8052 default_server;
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
# If you have a domain name, this is where to add it
|
||||||
|
server_name _;
|
||||||
|
keepalive_timeout 65;
|
||||||
|
|
||||||
|
# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
|
||||||
|
add_header Strict-Transport-Security max-age=15768000;
|
||||||
|
|
||||||
|
# Protect against click-jacking https://www.owasp.org/index.php/Testing_for_Clickjacking_(OTG-CLIENT-009)
|
||||||
|
add_header X-Frame-Options "DENY";
|
||||||
|
|
||||||
|
location /nginx_status {
|
||||||
|
stub_status on;
|
||||||
|
access_log off;
|
||||||
|
allow 127.0.0.1;
|
||||||
|
deny all;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /static/ {
|
||||||
|
alias /var/lib/awx/public/static/;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /favicon.ico { alias /var/lib/awx/public/static/favicon.ico; }
|
||||||
|
|
||||||
|
location /websocket {
|
||||||
|
# Pass request to the upstream alias
|
||||||
|
proxy_pass http://daphne;
|
||||||
|
# Require http version 1.1 to allow for upgrade requests
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
# We want proxy_buffering off for proxying to websockets.
|
||||||
|
proxy_buffering off;
|
||||||
|
# http://en.wikipedia.org/wiki/X-Forwarded-For
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
# enable this if you use HTTPS:
|
||||||
|
proxy_set_header X-Forwarded-Proto https;
|
||||||
|
# pass the Host: header from the client for the sake of redirects
|
||||||
|
proxy_set_header Host $http_host;
|
||||||
|
# We've set the Host header, so we don't need Nginx to muddle
|
||||||
|
# about with redirects
|
||||||
|
proxy_redirect off;
|
||||||
|
# Depending on the request value, set the Upgrade and
|
||||||
|
# connection headers
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection $connection_upgrade;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
# Add trailing / if missing
|
||||||
|
rewrite ^(.*)$http_host(.*[^/])$ $1$http_host$2/ permanent;
|
||||||
|
uwsgi_read_timeout 120s;
|
||||||
|
uwsgi_pass uwsgi;
|
||||||
|
include /etc/nginx/uwsgi_params;
|
||||||
|
{%- if extra_nginx_include is defined %}
|
||||||
|
include {{ extra_nginx_include }};
|
||||||
|
{%- endif %}
|
||||||
|
proxy_set_header X-Forwarded-Port 443;
|
||||||
|
uwsgi_param HTTP_X_FORWARDED_PORT 443;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
unixsocket /var/run/redis/redis.sock
|
||||||
|
unixsocketperm 660
|
||||||
|
port 0
|
||||||
|
bind 127.0.0.1
|
17
examples/azure-vote/README.md
Normal file
17
examples/azure-vote/README.md
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# Azure Vote Example
|
||||||
|
|
||||||
|
This example have two containers:
|
||||||
|
|
||||||
|
* backend: `redis` used as storage
|
||||||
|
* frontend: having supervisord, nginx, uwsgi/python
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
echo "HOST_PORT=8080" > .env
|
||||||
|
podman-compose up
|
||||||
|
```
|
||||||
|
|
||||||
|
after typing the commands above open your browser on the host port you picked above like
|
||||||
|
[http://localhost:8080/](http://localhost:8080/)
|
||||||
|
|
||||||
|
|
16
examples/azure-vote/docker-compose.yaml
Normal file
16
examples/azure-vote/docker-compose.yaml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
# from https://github.com/Azure-Samples/azure-voting-app-redis/blob/master/docker-compose.yaml
|
||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
azure-vote-back:
|
||||||
|
image: mcr.microsoft.com/oss/bitnami/redis:6.0.8
|
||||||
|
container_name: azure-vote-back
|
||||||
|
environment:
|
||||||
|
ALLOW_EMPTY_PASSWORD: "yes"
|
||||||
|
azure-vote-front:
|
||||||
|
image: mcr.microsoft.com/azuredocs/azure-vote-front:v1
|
||||||
|
environment:
|
||||||
|
REDIS: azure-vote-back
|
||||||
|
ports:
|
||||||
|
- "${HOST_PORT:-8080}:80"
|
||||||
|
|
31
examples/echo/README.md
Normal file
31
examples/echo/README.md
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
# Echo Service example
|
||||||
|
|
||||||
|
```
|
||||||
|
podman-compose up
|
||||||
|
```
|
||||||
|
|
||||||
|
Test the service with `curl like this`
|
||||||
|
|
||||||
|
```
|
||||||
|
$ curl -X POST -d "foobar" http://localhost:8080/; echo
|
||||||
|
|
||||||
|
CLIENT VALUES:
|
||||||
|
client_address=10.89.31.2
|
||||||
|
command=POST
|
||||||
|
real path=/
|
||||||
|
query=nil
|
||||||
|
request_version=1.1
|
||||||
|
request_uri=http://localhost:8080/
|
||||||
|
|
||||||
|
SERVER VALUES:
|
||||||
|
server_version=nginx: 1.10.0 - lua: 10001
|
||||||
|
|
||||||
|
HEADERS RECEIVED:
|
||||||
|
accept=*/*
|
||||||
|
content-length=6
|
||||||
|
content-type=application/x-www-form-urlencoded
|
||||||
|
host=localhost:8080
|
||||||
|
user-agent=curl/7.76.1
|
||||||
|
BODY:
|
||||||
|
foobar
|
||||||
|
```
|
8
examples/echo/docker-compose.yaml
Normal file
8
examples/echo/docker-compose.yaml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
web:
|
||||||
|
image: k8s.gcr.io/echoserver:1.4
|
||||||
|
ports:
|
||||||
|
- "${HOST_PORT:-8080}:8080"
|
||||||
|
|
12
examples/hello-app-redis/README.md
Normal file
12
examples/hello-app-redis/README.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# GCR Hello App Redis
|
||||||
|
|
||||||
|
A 6-node redis cluster using [Bitnami](https://github.com/bitnami/bitnami-docker-redis-cluster)
|
||||||
|
with a [simple hit counter](https://github.com/GoogleCloudPlatform/kubernetes-engine-samples/tree/main/hello-app-redis) that persists on that redis cluster
|
||||||
|
|
||||||
|
```
|
||||||
|
podman-compose up
|
||||||
|
```
|
||||||
|
|
||||||
|
then open your browser on [http://localhost:8080/](http://localhost:8080/)
|
||||||
|
|
||||||
|
|
67
examples/hello-app-redis/docker-compose.yaml
Normal file
67
examples/hello-app-redis/docker-compose.yaml
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
---
|
||||||
|
version: '3'
|
||||||
|
volumes:
|
||||||
|
redis-node1-data:
|
||||||
|
redis-node2-data:
|
||||||
|
redis-node3-data:
|
||||||
|
redis-node4-data:
|
||||||
|
redis-node5-data:
|
||||||
|
redis-data:
|
||||||
|
services:
|
||||||
|
web:
|
||||||
|
image: gcr.io/google-samples/hello-app-redis:1.0
|
||||||
|
depends_on:
|
||||||
|
- redis-cluster
|
||||||
|
ports:
|
||||||
|
- "${HOST_PORT:-8080}:8080"
|
||||||
|
redis-node1:
|
||||||
|
image: docker.io/bitnami/redis-cluster:6.2
|
||||||
|
volumes:
|
||||||
|
- redis-node1-data:/bitnami/redis/data
|
||||||
|
environment:
|
||||||
|
- ALLOW_EMPTY_PASSWORD=yes
|
||||||
|
- REDIS_NODES=redis-node1 redis-node2 redis-node3 redis-node4 redis-node5 redis-cluster
|
||||||
|
redis-node2:
|
||||||
|
image: docker.io/bitnami/redis-cluster:6.2
|
||||||
|
volumes:
|
||||||
|
- redis-node2-data:/bitnami/redis/data
|
||||||
|
environment:
|
||||||
|
- ALLOW_EMPTY_PASSWORD=yes
|
||||||
|
- REDIS_NODES=redis-node1 redis-node2 redis-node3 redis-node4 redis-node5 redis-cluster
|
||||||
|
redis-node3:
|
||||||
|
image: docker.io/bitnami/redis-cluster:6.2
|
||||||
|
volumes:
|
||||||
|
- redis-node3-data:/bitnami/redis/data
|
||||||
|
environment:
|
||||||
|
- ALLOW_EMPTY_PASSWORD=yes
|
||||||
|
- REDIS_NODES=redis-node1 redis-node2 redis-node3 redis-node4 redis-node5 redis-cluster
|
||||||
|
redis-node4:
|
||||||
|
image: docker.io/bitnami/redis-cluster:6.2
|
||||||
|
volumes:
|
||||||
|
- redis-node4-data:/bitnami/redis/data
|
||||||
|
environment:
|
||||||
|
- ALLOW_EMPTY_PASSWORD=yes
|
||||||
|
- REDIS_NODES=redis-node1 redis-node2 redis-node3 redis-node4 redis-node5 redis-cluster
|
||||||
|
redis-node5:
|
||||||
|
image: docker.io/bitnami/redis-cluster:6.2
|
||||||
|
volumes:
|
||||||
|
- redis-node5-data:/bitnami/redis/data
|
||||||
|
environment:
|
||||||
|
- ALLOW_EMPTY_PASSWORD=yes
|
||||||
|
- REDIS_NODES=redis-node1 redis-node2 redis-node3 redis-node4 redis-node5 redis-cluster
|
||||||
|
|
||||||
|
redis-cluster:
|
||||||
|
image: docker.io/bitnami/redis-cluster:6.2
|
||||||
|
volumes:
|
||||||
|
- redis-data:/bitnami/redis/data
|
||||||
|
depends_on:
|
||||||
|
- redis-node1
|
||||||
|
- redis-node2
|
||||||
|
- redis-node3
|
||||||
|
- redis-node4
|
||||||
|
- redis-node5
|
||||||
|
environment:
|
||||||
|
- ALLOW_EMPTY_PASSWORD=yes
|
||||||
|
- REDIS_NODES=redis-node1 redis-node2 redis-node3 redis-node4 redis-node5 redis-cluster
|
||||||
|
- REDIS_CLUSTER_CREATOR=yes
|
||||||
|
|
10
examples/hello-app/README.md
Normal file
10
examples/hello-app/README.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# GCR Hello App
|
||||||
|
|
||||||
|
A small ~2MB image, type
|
||||||
|
|
||||||
|
```
|
||||||
|
podman-compose up
|
||||||
|
```
|
||||||
|
|
||||||
|
then open your browser on [http://localhost:8080/](http://localhost:8080/)
|
||||||
|
|
8
examples/hello-app/docker-compose.yaml
Normal file
8
examples/hello-app/docker-compose.yaml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
web:
|
||||||
|
image: gcr.io/google-samples/hello-app:1.0
|
||||||
|
ports:
|
||||||
|
- "${HOST_PORT:-8080}:8080"
|
||||||
|
|
12
examples/hello-python/Dockerfile
Normal file
12
examples/hello-python/Dockerfile
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
FROM python:3.9-alpine
|
||||||
|
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
COPY requirements.txt ./
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
CMD [ "python", "-m", "app.web" ]
|
||||||
|
EXPOSE 8080
|
||||||
|
|
8
examples/hello-python/README.md
Normal file
8
examples/hello-python/README.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# Simple Python Demo
|
||||||
|
## A Redis counter
|
||||||
|
|
||||||
|
```
|
||||||
|
podman-compose up -d
|
||||||
|
curl localhost:8080/
|
||||||
|
curl localhost:8080/hello.json
|
||||||
|
```
|
39
examples/hello-python/app/web.py
Normal file
39
examples/hello-python/app/web.py
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# pylint: disable=import-error
|
||||||
|
# pylint: disable=unused-import
|
||||||
|
import asyncio # noqa: F401
|
||||||
|
import os
|
||||||
|
|
||||||
|
import aioredis
|
||||||
|
from aiohttp import web
|
||||||
|
|
||||||
|
REDIS_HOST = os.environ.get("REDIS_HOST", "localhost")
|
||||||
|
REDIS_PORT = int(os.environ.get("REDIS_PORT", "6379"))
|
||||||
|
REDIS_DB = int(os.environ.get("REDIS_DB", "0"))
|
||||||
|
|
||||||
|
redis = aioredis.from_url(f"redis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_DB}")
|
||||||
|
app = web.Application()
|
||||||
|
routes = web.RouteTableDef()
|
||||||
|
|
||||||
|
|
||||||
|
@routes.get("/")
|
||||||
|
async def hello(request): # pylint: disable=unused-argument
|
||||||
|
counter = await redis.incr("mycounter")
|
||||||
|
return web.Response(text=f"counter={counter}")
|
||||||
|
|
||||||
|
|
||||||
|
@routes.get("/hello.json")
|
||||||
|
async def hello_json(request): # pylint: disable=unused-argument
|
||||||
|
counter = await redis.incr("mycounter")
|
||||||
|
data = {"counter": counter}
|
||||||
|
return web.json_response(data)
|
||||||
|
|
||||||
|
|
||||||
|
app.add_routes(routes)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
web.run_app(app, port=8080)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
21
examples/hello-python/docker-compose.yaml
Normal file
21
examples/hello-python/docker-compose.yaml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
version: '3'
|
||||||
|
volumes:
|
||||||
|
redis:
|
||||||
|
services:
|
||||||
|
redis:
|
||||||
|
read_only: true
|
||||||
|
image: docker.io/redis:alpine
|
||||||
|
command: ["redis-server", "--appendonly", "yes", "--notify-keyspace-events", "Ex"]
|
||||||
|
volumes:
|
||||||
|
- redis:/data
|
||||||
|
web:
|
||||||
|
read_only: true
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
image: hello-py-aioweb
|
||||||
|
ports:
|
||||||
|
- 8080:8080
|
||||||
|
environment:
|
||||||
|
REDIS_HOST: redis
|
||||||
|
|
3
examples/hello-python/requirements.txt
Normal file
3
examples/hello-python/requirements.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
aiohttp
|
||||||
|
aioredis
|
||||||
|
# aioredis[hiredis]
|
71
examples/nodeproj/.eslintrc.json
Normal file
71
examples/nodeproj/.eslintrc.json
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"node": true,
|
||||||
|
"es6": true
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"import/resolver": {
|
||||||
|
"node": {
|
||||||
|
"extensions": [".js", ".mjs", ".ts", ".cjs"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 2020,
|
||||||
|
"sourceType": "module",
|
||||||
|
"allowImportExportEverywhere": true
|
||||||
|
},
|
||||||
|
"extends": [
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:import/errors",
|
||||||
|
"plugin:import/warnings",
|
||||||
|
"plugin:import/typescript",
|
||||||
|
"plugin:promise/recommended",
|
||||||
|
"google",
|
||||||
|
"plugin:security/recommended"
|
||||||
|
],
|
||||||
|
"plugins": ["promise", "security", "import"],
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": "public/**/*.min.js",
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"node": false,
|
||||||
|
"es6": false
|
||||||
|
},
|
||||||
|
"parserOptions": {
|
||||||
|
"sourceType": "script"
|
||||||
|
},
|
||||||
|
"extends": ["plugin:compat/recommended"],
|
||||||
|
"plugins": [],
|
||||||
|
"rules": {
|
||||||
|
"no-var": ["off"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"security/detect-non-literal-fs-filename":["off"],
|
||||||
|
"security/detect-object-injection":["off"],
|
||||||
|
"camelcase": ["off"],
|
||||||
|
"no-console": ["off"],
|
||||||
|
"require-jsdoc": ["off"],
|
||||||
|
"one-var": ["off"],
|
||||||
|
"guard-for-in": ["off"],
|
||||||
|
"max-len": [
|
||||||
|
"warn",
|
||||||
|
{
|
||||||
|
"ignoreComments": true,
|
||||||
|
"ignoreTrailingComments": true,
|
||||||
|
"ignoreUrls": true,
|
||||||
|
"code": 200
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"indent": ["warn", 4],
|
||||||
|
"no-unused-vars": ["warn"],
|
||||||
|
"no-extra-semi": ["warn"],
|
||||||
|
"linebreak-style": ["error", "unix"],
|
||||||
|
"quotes": ["warn", "double"],
|
||||||
|
"semi": ["error", "always"]
|
||||||
|
}
|
||||||
|
}
|
5
examples/nodeproj/.gitignore
vendored
Normal file
5
examples/nodeproj/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
local.env
|
||||||
|
.env
|
||||||
|
*.pid
|
||||||
|
node_modules
|
||||||
|
|
1
examples/nodeproj/.home/.gitignore
vendored
Normal file
1
examples/nodeproj/.home/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
*
|
16
examples/nodeproj/README.md
Normal file
16
examples/nodeproj/README.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# How to run example
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
cp example.local.env local.env
|
||||||
|
cp example.env .env
|
||||||
|
cat local.env
|
||||||
|
cat .env
|
||||||
|
echo "UID=$UID" >> .env
|
||||||
|
cat .env
|
||||||
|
podman-compose build
|
||||||
|
podman-compose run --rm --no-deps init
|
||||||
|
podman-compose up
|
||||||
|
```
|
||||||
|
|
12
examples/nodeproj/containers/node16-runtime/Dockerfile
Normal file
12
examples/nodeproj/containers/node16-runtime/Dockerfile
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
FROM registry.fedoraproject.org/fedora-minimal:35
|
||||||
|
ARG NODE_VER=16
|
||||||
|
# microdnf -y module enable nodejs:${NODE_VER}
|
||||||
|
RUN \
|
||||||
|
echo -e "[nodejs]\nname=nodejs\nstream=${NODE_VER}\nprofiles=\nstate=enabled\n" > /etc/dnf/modules.d/nodejs.module && \
|
||||||
|
microdnf -y install shadow-utils nodejs zopfli findutils busybox && \
|
||||||
|
microdnf clean all
|
||||||
|
RUN adduser -d /app app && mkdir -p /app/code/.home && chown app:app -R /app/code && chmod 711 /app /app/code/.home && usermod -d /app/code/.home app
|
||||||
|
ENV XDG_CONFIG_HOME=/app/code/.home
|
||||||
|
ENV HOME=/app/code/.home
|
||||||
|
WORKDIR /app/code
|
||||||
|
|
48
examples/nodeproj/docker-compose.yml
Normal file
48
examples/nodeproj/docker-compose.yml
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
version: '3'
|
||||||
|
volumes:
|
||||||
|
redis:
|
||||||
|
services:
|
||||||
|
redis:
|
||||||
|
read_only: true
|
||||||
|
image: docker.io/redis:alpine
|
||||||
|
command: ["redis-server", "--appendonly", "yes", "--notify-keyspace-events", "Ex"]
|
||||||
|
volumes:
|
||||||
|
- redis:/data
|
||||||
|
tmpfs:
|
||||||
|
- /tmp
|
||||||
|
- /var/run
|
||||||
|
- /run
|
||||||
|
init:
|
||||||
|
read_only: true
|
||||||
|
#userns_mode: keep-id
|
||||||
|
user: ${UID:-1000}
|
||||||
|
build:
|
||||||
|
context: ./containers/${NODE_IMG:-node16-runtime}
|
||||||
|
image: ${NODE_IMG:-node16-runtime}
|
||||||
|
env_file:
|
||||||
|
- local.env
|
||||||
|
volumes:
|
||||||
|
- .:/app/code
|
||||||
|
command: ["/bin/sh", "-c", "mkdir -p ~/; [ -d ./node_modules ] && echo '** node_modules exists' || npm install"]
|
||||||
|
tmpfs:
|
||||||
|
- /tmp
|
||||||
|
- /run
|
||||||
|
task:
|
||||||
|
extends:
|
||||||
|
service: init
|
||||||
|
command: ["npm", "run", "cli", "--", "task"]
|
||||||
|
links:
|
||||||
|
- redis
|
||||||
|
depends_on:
|
||||||
|
- redis
|
||||||
|
web:
|
||||||
|
extends:
|
||||||
|
service: init
|
||||||
|
command: ["npm", "run", "cli", "--", "web"]
|
||||||
|
ports:
|
||||||
|
- ${WEB_LISTEN_PORT:-3000}:3000
|
||||||
|
depends_on:
|
||||||
|
- redis
|
||||||
|
links:
|
||||||
|
- mongo
|
||||||
|
|
3
examples/nodeproj/example.env
Normal file
3
examples/nodeproj/example.env
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
WEB_LISTEN_PORT=3000
|
||||||
|
# pass UID= your IDE user
|
||||||
|
|
2
examples/nodeproj/example.local.env
Normal file
2
examples/nodeproj/example.local.env
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
REDIS_HOST=redis
|
||||||
|
|
6
examples/nodeproj/index.js
Normal file
6
examples/nodeproj/index.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#! /usr/bin/env node
|
||||||
|
"use strict";
|
||||||
|
import {start} from "./lib";
|
||||||
|
|
||||||
|
start();
|
||||||
|
|
14
examples/nodeproj/jsconfig.json
Normal file
14
examples/nodeproj/jsconfig.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es2020",
|
||||||
|
"module": "es2020",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"allowSyntheticDefaultImports": true
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"index.js"
|
||||||
|
],
|
||||||
|
"include": [
|
||||||
|
"lib/**/*.js"
|
||||||
|
]
|
||||||
|
}
|
31
examples/nodeproj/lib/commands/task.js
Normal file
31
examples/nodeproj/lib/commands/task.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
"use strict";
|
||||||
|
import {proj} from "../proj";
|
||||||
|
|
||||||
|
async function loop() {
|
||||||
|
const poped = await proj.predis.blpop("queue", 5);
|
||||||
|
const task_desc_s = poped[1];
|
||||||
|
let task_desc;
|
||||||
|
try {
|
||||||
|
task_desc = JSON.parse(task_desc_s);
|
||||||
|
} catch (e) {
|
||||||
|
console.exception(e);
|
||||||
|
}
|
||||||
|
console.info("got task "+task_desc.func);
|
||||||
|
const func = task_desc.func;
|
||||||
|
const args = task_desc.args;
|
||||||
|
if (typeof(proj.tasks[func])!="function") {
|
||||||
|
console.log(`task ${func} not found`);
|
||||||
|
process.exit(-1)
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await ((this.tasks[func])(...args));
|
||||||
|
} catch (e) {
|
||||||
|
console.exception(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function start() {
|
||||||
|
while(true) {
|
||||||
|
loop();
|
||||||
|
}
|
||||||
|
}
|
21
examples/nodeproj/lib/commands/web.js
Normal file
21
examples/nodeproj/lib/commands/web.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
"use strict";
|
||||||
|
import {proj} from "../proj";
|
||||||
|
|
||||||
|
import http from "http";
|
||||||
|
import express from "express";
|
||||||
|
|
||||||
|
|
||||||
|
export async function start() {
|
||||||
|
const app = express();
|
||||||
|
const server = http.createServer(app);
|
||||||
|
|
||||||
|
// Routing
|
||||||
|
app.use(express.static(proj.config.basedir + "/public"));
|
||||||
|
app.get("/healthz", function(req, res) {
|
||||||
|
res.send("ok@"+Date.now());
|
||||||
|
});
|
||||||
|
|
||||||
|
server.listen(proj.config.LISTEN_PORT, proj.config.LISTEN_HOST, function() {
|
||||||
|
console.warn(`listening at port ${proj.config.LISTEN_PORT}`);
|
||||||
|
});
|
||||||
|
}
|
24
examples/nodeproj/package.json
Normal file
24
examples/nodeproj/package.json
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"name": "nodeproj",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "nodejs example project",
|
||||||
|
"exports": {
|
||||||
|
".": "./index.js",
|
||||||
|
"./lib": "./lib"
|
||||||
|
},
|
||||||
|
"main": "index.js",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"cli": "nodemon -w lib -w index.js --es-module-specifier-resolution=node ./index.js"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"express": "~4.16.4",
|
||||||
|
"redis": "^3.1.2"
|
||||||
|
},
|
||||||
|
"private": true,
|
||||||
|
"author": "",
|
||||||
|
"license": "proprietary",
|
||||||
|
"devDependencies": {
|
||||||
|
"nodemon": "^2.0.14"
|
||||||
|
}
|
||||||
|
}
|
18
examples/nodeproj/public/index.html
Normal file
18
examples/nodeproj/public/index.html
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Vote</title>
|
||||||
|
<link rel="stylesheet" href="https://unpkg.com/browse/normalize.css@8.0.1/normalize.css">
|
||||||
|
<link rel="stylesheet" href="styles.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>This is a Heading</h1>
|
||||||
|
<p>This is a paragraph.</p>
|
||||||
|
</body>
|
||||||
|
<script type="text/javascript" src="main.css"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
//<![CDATA[
|
||||||
|
console.log("loaded");
|
||||||
|
//]]>
|
||||||
|
</script>
|
||||||
|
</html>
|
11
examples/nvidia-smi/docker-compose.yaml
Normal file
11
examples/nvidia-smi/docker-compose.yaml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
services:
|
||||||
|
test:
|
||||||
|
image: nvidia/cuda:12.3.1-base-ubuntu20.04
|
||||||
|
command: nvidia-smi
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
reservations:
|
||||||
|
devices:
|
||||||
|
- driver: nvidia
|
||||||
|
count: 1
|
||||||
|
capabilities: [gpu]
|
24
examples/wordpress/docker-compose.yaml
Normal file
24
examples/wordpress/docker-compose.yaml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
volumes:
|
||||||
|
db_data:
|
||||||
|
services:
|
||||||
|
wordpress:
|
||||||
|
image: docker.io/library/wordpress:latest
|
||||||
|
ports:
|
||||||
|
- 8080:80
|
||||||
|
environment:
|
||||||
|
- WORDPRESS_DB_HOST=db
|
||||||
|
- WORDPRESS_DB_USER=wordpress
|
||||||
|
- WORDPRESS_DB_PASSWORD=password
|
||||||
|
- WORDPRESS_DB_NAME=wordpress
|
||||||
|
db:
|
||||||
|
image: docker.io/library/mariadb:10.6.4-focal
|
||||||
|
command: '--default-authentication-plugin=mysql_native_password'
|
||||||
|
volumes:
|
||||||
|
- db_data:/var/lib/mysql
|
||||||
|
environment:
|
||||||
|
- MYSQL_ROOT_PASSWORD=somewordpress
|
||||||
|
- MYSQL_DATABASE=wordpress
|
||||||
|
- MYSQL_USER=wordpress
|
||||||
|
- MYSQL_PASSWORD=password
|
||||||
|
|
13
newsfragments/README.txt
Normal file
13
newsfragments/README.txt
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
This is the directory for news fragments used by towncrier: https://github.com/hawkowl/towncrier
|
||||||
|
|
||||||
|
You create a news fragment in this directory when you make a change, and the file gets removed from
|
||||||
|
this directory when the news is published.
|
||||||
|
|
||||||
|
towncrier has a few standard types of news fragments, signified by the file extension. These are:
|
||||||
|
|
||||||
|
.feature: Signifying a new feature.
|
||||||
|
.bugfix: Signifying a bug fix.
|
||||||
|
.doc: Signifying a documentation improvement.
|
||||||
|
.removal: Signifying a deprecation or removal of public API.
|
||||||
|
.change: Signifying a change of behavior
|
||||||
|
.misc: Miscellaneous change
|
3794
podman_compose.py
3794
podman_compose.py
File diff suppressed because it is too large
Load Diff
55
pyproject.toml
Normal file
55
pyproject.toml
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
[tool.ruff]
|
||||||
|
line-length = 100
|
||||||
|
target-version = "py38"
|
||||||
|
|
||||||
|
[tool.ruff.lint]
|
||||||
|
select = ["W", "E", "F", "I"]
|
||||||
|
ignore = [
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.ruff.lint.isort]
|
||||||
|
force-single-line = true
|
||||||
|
|
||||||
|
[tool.ruff.format]
|
||||||
|
preview = true # needed for quote-style
|
||||||
|
quote-style = "preserve"
|
||||||
|
|
||||||
|
[tool.towncrier]
|
||||||
|
package = "podman_compose"
|
||||||
|
package_dir = "master"
|
||||||
|
directory = "newsfragments"
|
||||||
|
filename = "docs/Changelog-new.md"
|
||||||
|
template = "scripts/Changelog-template.jinja"
|
||||||
|
title_format = "Version {version} ({project_date})"
|
||||||
|
[[tool.towncrier.section]]
|
||||||
|
path = ""
|
||||||
|
|
||||||
|
[[tool.towncrier.type]]
|
||||||
|
directory = "feature"
|
||||||
|
name = "Features"
|
||||||
|
showcontent = true
|
||||||
|
|
||||||
|
[[tool.towncrier.type]]
|
||||||
|
directory = "change"
|
||||||
|
name = "Changes"
|
||||||
|
showcontent = true
|
||||||
|
|
||||||
|
[[tool.towncrier.type]]
|
||||||
|
directory = "bugfix"
|
||||||
|
name = "Bug fixes"
|
||||||
|
showcontent = true
|
||||||
|
|
||||||
|
[[tool.towncrier.type]]
|
||||||
|
directory = "doc"
|
||||||
|
name = "Improved Documentation"
|
||||||
|
showcontent = true
|
||||||
|
|
||||||
|
[[tool.towncrier.type]]
|
||||||
|
directory = "removal"
|
||||||
|
name = "Deprecations and Removals"
|
||||||
|
showcontent = true
|
||||||
|
|
||||||
|
[[tool.towncrier.type]]
|
||||||
|
directory = "misc"
|
||||||
|
name = "Misc"
|
||||||
|
showcontent = true
|
33
scripts/Changelog-template.jinja
Normal file
33
scripts/Changelog-template.jinja
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
{% for section, _ in sections|dictsort(by='key') %}
|
||||||
|
{% set underline = "-" %}
|
||||||
|
{% if section %}
|
||||||
|
{{section}}
|
||||||
|
{{ underline * section|length }}{% set underline = "~" %}
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{% if sections[section] %}
|
||||||
|
{% for category, val in definitions|dictsort if category in sections[section]%}
|
||||||
|
|
||||||
|
{{ definitions[category]['name'] }}
|
||||||
|
{{ underline * definitions[category]['name']|length }}
|
||||||
|
|
||||||
|
{% for text, values in sections[section][category]|dictsort(by='value') %}
|
||||||
|
- {{ text }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% if sections[section][category]|length == 0 %}
|
||||||
|
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
(venv) p12@exec-desktop:~/cod
|
16
scripts/download_and_build_podman-compose.sh
Normal file
16
scripts/download_and_build_podman-compose.sh
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Delete repository dir
|
||||||
|
rm -rf podman-compose-src
|
||||||
|
|
||||||
|
# Clone repository
|
||||||
|
git clone https://github.com/containers/podman-compose podman-compose-src
|
||||||
|
|
||||||
|
# Generate binary
|
||||||
|
sh podman-compose-src/scripts/generate_binary_using_dockerfile.sh
|
||||||
|
|
||||||
|
# Move binary outside repo's dir
|
||||||
|
mv podman-compose-src/podman-compose .
|
||||||
|
|
||||||
|
# Delete repository dir
|
||||||
|
rm -rf podman-compose-src
|
57
scripts/generate_binary_using_dockerfile.sh
Normal file
57
scripts/generate_binary_using_dockerfile.sh
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Find an available container tool (docker or podman)
|
||||||
|
find_container_tool() {
|
||||||
|
if command -v docker > /dev/null 2>&1; then
|
||||||
|
echo "sudo docker"
|
||||||
|
elif command -v podman > /dev/null 2>&1; then
|
||||||
|
echo "podman"
|
||||||
|
else
|
||||||
|
echo "Error: Neither docker nor podman is available." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Determine which container tool to use
|
||||||
|
CONTAINER_TOOL=$(find_container_tool)
|
||||||
|
|
||||||
|
# Locate the directory containing dockerfile (root)
|
||||||
|
PROJECT_ROOT_DIR="$(cd "$(dirname "$0")" && pwd)/.."
|
||||||
|
|
||||||
|
# Check SELinux status and set appropriate mount option
|
||||||
|
check_selinux() {
|
||||||
|
if command -v getenforce > /dev/null 2>&1; then
|
||||||
|
SELINUX_STATUS=$(getenforce)
|
||||||
|
if [ "$SELINUX_STATUS" = "Enforcing" ] || [ "$SELINUX_STATUS" = "Permissive" ]; then
|
||||||
|
echo ":z"
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
elif [ -f /sys/fs/selinux/enforce ]; then
|
||||||
|
if [ "$(cat /sys/fs/selinux/enforce)" = "1" ]; then
|
||||||
|
echo ":z"
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get the SELinux option for volume mounts if SELinux is enforcing or permissive
|
||||||
|
SELINUX=$(check_selinux)
|
||||||
|
|
||||||
|
# Build binary
|
||||||
|
$CONTAINER_TOOL image rm build-podman-compose
|
||||||
|
|
||||||
|
if expr "$CONTAINER_TOOL" : '.*docker.*' >/dev/null; then
|
||||||
|
$CONTAINER_TOOL build -t build-podman-compose "$PROJECT_ROOT_DIR"
|
||||||
|
$CONTAINER_TOOL run --name build-podman-compose build-podman-compose
|
||||||
|
$CONTAINER_TOOL cp build-podman-compose:/result/podman-compose "$PROJECT_ROOT_DIR/podman-compose"
|
||||||
|
$CONTAINER_TOOL container stop build-podman-compose
|
||||||
|
$CONTAINER_TOOL container rm -f build-podman-compose
|
||||||
|
else
|
||||||
|
$CONTAINER_TOOL build -v "$PROJECT_ROOT_DIR:/result$SELINUX" -t build-podman-compose "$PROJECT_ROOT_DIR"
|
||||||
|
fi
|
||||||
|
$CONTAINER_TOOL image rm python:3.11-slim
|
||||||
|
$CONTAINER_TOOL image rm build-podman-compose
|
@ -1,6 +1,18 @@
|
|||||||
#!/usr/bin/env bash
|
#!/bin/bash
|
||||||
./scripts/uninstall.sh
|
|
||||||
./scripts/clean_up.sh
|
set -e
|
||||||
python3 setup.py register
|
|
||||||
python3 setup.py sdist bdist_wheel
|
if [ $# -ne 1 ]; then
|
||||||
twine upload dist/*
|
echo "Usage: make_release.sh VERSION"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
VERSION=$1
|
||||||
|
|
||||||
|
sed "s/__version__ = .*/__version__ = \"$VERSION\"/g" -i podman_compose.py
|
||||||
|
git add podman_compose.py
|
||||||
|
git commit -m "Release $VERSION"
|
||||||
|
|
||||||
|
git tag "v$VERSION" -m "v$VERSION" -s
|
||||||
|
|
||||||
|
git push ssh://github.com/containers/podman-compose main "v$VERSION"
|
||||||
|
14
scripts/make_release_notes.sh
Executable file
14
scripts/make_release_notes.sh
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ $# -ne 1 ]; then
|
||||||
|
echo "Usage: make_release_notes.sh VERSION"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
VERSION=$1
|
||||||
|
towncrier build --version "$VERSION" --yes
|
||||||
|
git mv "docs/Changelog-new.md" "docs/Changelog-$VERSION.md"
|
||||||
|
git add "newsfragments/"
|
||||||
|
git commit -m "Release notes for $VERSION"
|
6
scripts/make_release_upload.sh
Executable file
6
scripts/make_release_upload.sh
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
./scripts/uninstall.sh
|
||||||
|
./scripts/clean_up.sh
|
||||||
|
python3 setup.py register
|
||||||
|
python3 setup.py sdist bdist_wheel
|
||||||
|
twine upload dist/*
|
@ -3,3 +3,7 @@ universal = 1
|
|||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
version = attr: podman_compose.__version__
|
version = attr: podman_compose.__version__
|
||||||
|
|
||||||
|
[flake8]
|
||||||
|
# The GitHub editor is 127 chars wide
|
||||||
|
max-line-length=127
|
48
setup.py
48
setup.py
@ -1,49 +1,49 @@
|
|||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from setuptools import setup
|
from setuptools import setup
|
||||||
|
|
||||||
try:
|
try:
|
||||||
readme = open(os.path.join(os.path.dirname(__file__), 'README.md')).read()
|
README = open(os.path.join(os.path.dirname(__file__), "README.md"), encoding="utf-8").read()
|
||||||
except:
|
except: # noqa: E722 # pylint: disable=bare-except
|
||||||
readme = ''
|
README = ""
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='podman-compose',
|
name="podman-compose",
|
||||||
description="A script to run docker-compose.yml using podman",
|
description="A script to run docker-compose.yml using podman",
|
||||||
long_description=readme,
|
long_description=README,
|
||||||
long_description_content_type='text/markdown',
|
long_description_content_type="text/markdown",
|
||||||
classifiers=[
|
classifiers=[
|
||||||
"Programming Language :: Python",
|
"Programming Language :: Python",
|
||||||
"Programming Language :: Python :: 3",
|
"Programming Language :: Python :: 3",
|
||||||
"Programming Language :: Python :: 3.5",
|
"Programming Language :: Python :: 3.9",
|
||||||
"Programming Language :: Python :: 3.6",
|
"Programming Language :: Python :: 3.10",
|
||||||
"Programming Language :: Python :: 3.7",
|
"Programming Language :: Python :: 3.11",
|
||||||
|
"Programming Language :: Python :: 3.12",
|
||||||
|
"Programming Language :: Python :: 3.13",
|
||||||
"Intended Audience :: Developers",
|
"Intended Audience :: Developers",
|
||||||
"Operating System :: OS Independent",
|
"Operating System :: OS Independent",
|
||||||
"Development Status :: 3 - Alpha",
|
"Development Status :: 3 - Alpha",
|
||||||
"Topic :: Software Development :: Build Tools",
|
"Topic :: Software Development :: Build Tools",
|
||||||
"License :: OSI Approved :: GNU General Public License v2 (GPLv2)",
|
"License :: OSI Approved :: GNU General Public License v2 (GPLv2)",
|
||||||
],
|
],
|
||||||
keywords='podman, podman-compose',
|
keywords="podman, podman-compose",
|
||||||
author='Muayyad Alsadi',
|
author="Muayyad Alsadi",
|
||||||
author_email='alsadi@gmail.com',
|
author_email="alsadi@gmail.com",
|
||||||
url='https://github.com/containers/podman-compose',
|
url="https://github.com/containers/podman-compose",
|
||||||
py_modules=['podman_compose'],
|
py_modules=["podman_compose"],
|
||||||
entry_points={
|
entry_points={"console_scripts": ["podman-compose = podman_compose:main"]},
|
||||||
'console_scripts': [
|
|
||||||
'podman-compose = podman_compose:main'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
license='GPL-2.0-only',
|
license="GPL-2.0-only",
|
||||||
install_requires=[
|
install_requires=[
|
||||||
'pyyaml',
|
"pyyaml",
|
||||||
'python-dotenv',
|
"python-dotenv",
|
||||||
],
|
],
|
||||||
|
extras_require={"devel": ["ruff", "pre-commit", "coverage", "parameterized"]},
|
||||||
# test_suite='tests',
|
# test_suite='tests',
|
||||||
# tests_require=[
|
# tests_require=[
|
||||||
# 'coverage',
|
# 'coverage',
|
||||||
# 'pytest-cov',
|
|
||||||
# 'pytest',
|
|
||||||
# 'tox',
|
# 'tox',
|
||||||
# ]
|
# ]
|
||||||
)
|
)
|
||||||
|
@ -1,8 +1,34 @@
|
|||||||
# The order of packages is significant, because pip processes them in the order
|
-e .
|
||||||
# of appearance. Changing the order has an impact on the overall integration
|
coverage==7.4.3
|
||||||
# process, which may cause wedges in the gate later.
|
parameterized==0.9.0
|
||||||
|
pytest==8.0.2
|
||||||
|
tox==4.13.0
|
||||||
|
ruff==0.3.1
|
||||||
|
pylint==3.1.0
|
||||||
|
|
||||||
coverage
|
# The packages below are transitive dependencies of the packages above and are included here
|
||||||
pytest-cov
|
# to make testing reproducible.
|
||||||
pytest
|
# To refresh, create a new virtualenv and do:
|
||||||
tox
|
# pip install -r requirements.txt -r test-requirements.txt
|
||||||
|
# pip freeze > test-requirements.txt
|
||||||
|
# and edit test-requirements.txt to add this comment
|
||||||
|
|
||||||
|
astroid==3.1.0
|
||||||
|
cachetools==5.3.3
|
||||||
|
chardet==5.2.0
|
||||||
|
colorama==0.4.6
|
||||||
|
dill==0.3.8
|
||||||
|
distlib==0.3.8
|
||||||
|
filelock==3.13.1
|
||||||
|
iniconfig==2.0.0
|
||||||
|
isort==5.13.2
|
||||||
|
mccabe==0.7.0
|
||||||
|
packaging==23.2
|
||||||
|
platformdirs==4.2.0
|
||||||
|
pluggy==1.4.0
|
||||||
|
pyproject-api==1.6.1
|
||||||
|
python-dotenv==1.0.1
|
||||||
|
PyYAML==6.0.1
|
||||||
|
requests
|
||||||
|
tomlkit==0.12.4
|
||||||
|
virtualenv==20.25.1
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
# Test podman-compose with build
|
|
||||||
|
|
||||||
```
|
|
||||||
podman-compose build
|
|
||||||
podman-compose up -d
|
|
||||||
curl http://localhost:8080/index.txt
|
|
||||||
curl http://localhost:8000/index.txt
|
|
||||||
podman inspect my-busybox-httpd2
|
|
||||||
podman-compose down
|
|
||||||
```
|
|
||||||
|
|
||||||
expected output would be something like
|
|
||||||
|
|
||||||
```
|
|
||||||
2019-09-03T15:16:38+0000
|
|
||||||
ALT buildno=2 port 8000 2019-09-03T15:16:38+0000
|
|
||||||
{
|
|
||||||
...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
as you can see we were able to override buildno to be 2 instead of 1,
|
|
||||||
and httpd_port to 8000.
|
|
||||||
|
|
||||||
NOTE: build labels are not passed to `podman build`
|
|
@ -1,4 +0,0 @@
|
|||||||
|
|
||||||
```
|
|
||||||
podman-compose run --rm sleep /bin/sh -c 'wget -O - http://localhost:8000/hosts'
|
|
||||||
```
|
|
@ -1,24 +0,0 @@
|
|||||||
version: "3.7"
|
|
||||||
services:
|
|
||||||
web:
|
|
||||||
image: busybox
|
|
||||||
command: ["/bin/busybox", "httpd", "-f", "-h", "/etc/", "-p", "8000"]
|
|
||||||
tmpfs:
|
|
||||||
- /run
|
|
||||||
- /tmp
|
|
||||||
sleep:
|
|
||||||
image: busybox
|
|
||||||
command: ["/bin/busybox", "sh", "-c", "sleep 3600"]
|
|
||||||
depends_on: "web"
|
|
||||||
tmpfs:
|
|
||||||
- /run
|
|
||||||
- /tmp
|
|
||||||
sleep2:
|
|
||||||
image: busybox
|
|
||||||
command: ["/bin/busybox", "sh", "-c", "sleep 3600"]
|
|
||||||
depends_on:
|
|
||||||
- sleep
|
|
||||||
tmpfs:
|
|
||||||
- /run
|
|
||||||
- /tmp
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
|||||||
running the following command should give myval2
|
|
||||||
|
|
||||||
```
|
|
||||||
podman_compose run -l monkey -e ZZVAR1=myval2 env-test
|
|
||||||
```
|
|
@ -1,15 +0,0 @@
|
|||||||
We have service named sh1 that exits with code 1 and sh2 that exists with code 2
|
|
||||||
|
|
||||||
```
|
|
||||||
podman-compose up --exit-code-from=sh1
|
|
||||||
echo $?
|
|
||||||
```
|
|
||||||
|
|
||||||
the above should give 1.
|
|
||||||
|
|
||||||
```
|
|
||||||
podman-compose up --exit-code-from=sh2
|
|
||||||
echo $?
|
|
||||||
```
|
|
||||||
|
|
||||||
the above should give 2.
|
|
@ -1,21 +0,0 @@
|
|||||||
version: "3"
|
|
||||||
services:
|
|
||||||
too_long:
|
|
||||||
image: busybox
|
|
||||||
command: ["/bin/busybox", "sh", "-c", "sleep 3600; exit 0"]
|
|
||||||
tmpfs:
|
|
||||||
- /run
|
|
||||||
- /tmp
|
|
||||||
sh1:
|
|
||||||
image: busybox
|
|
||||||
command: ["/bin/busybox", "sh", "-c", "sleep 5; exit 1"]
|
|
||||||
tmpfs:
|
|
||||||
- /run
|
|
||||||
- /tmp
|
|
||||||
sh2:
|
|
||||||
image: busybox
|
|
||||||
command: ["/bin/busybox", "sh", "-c", "sleep 5; exit 2"]
|
|
||||||
tmpfs:
|
|
||||||
- /run
|
|
||||||
- /tmp
|
|
||||||
|
|
12
tests/integration/__init__.py
Normal file
12
tests/integration/__init__.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
|
def create_base_test_image():
|
||||||
|
subprocess.check_call(
|
||||||
|
['podman', 'build', '-t', 'nopush/podman-compose-test', '.'],
|
||||||
|
cwd=os.path.join(os.path.dirname(__file__), "base_image"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
create_base_test_image()
|
14
tests/integration/additional_contexts/README.md
Normal file
14
tests/integration/additional_contexts/README.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# Test podman-compose with build.additional_contexts
|
||||||
|
|
||||||
|
```
|
||||||
|
podman-compose build
|
||||||
|
podman-compose up
|
||||||
|
podman-compose down
|
||||||
|
```
|
||||||
|
|
||||||
|
expected output would be
|
||||||
|
|
||||||
|
```
|
||||||
|
[dict] | Data for dict
|
||||||
|
[list] | Data for list
|
||||||
|
```
|
@ -0,0 +1 @@
|
|||||||
|
Data for dict
|
@ -0,0 +1 @@
|
|||||||
|
Data for list
|
3
tests/integration/additional_contexts/project/Dockerfile
Normal file
3
tests/integration/additional_contexts/project/Dockerfile
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
FROM busybox
|
||||||
|
COPY --from=data data.txt /data/data.txt
|
||||||
|
CMD ["busybox", "cat", "/data/data.txt"]
|
@ -0,0 +1,12 @@
|
|||||||
|
version: "3.7"
|
||||||
|
services:
|
||||||
|
dict:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
additional_contexts:
|
||||||
|
data: ../data_for_dict
|
||||||
|
list:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
additional_contexts:
|
||||||
|
- data=../data_for_list
|
6
tests/integration/base_image/Dockerfile
Normal file
6
tests/integration/base_image/Dockerfile
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
FROM docker.io/library/debian:bookworm-slim
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get install -y \
|
||||||
|
dumb-init \
|
||||||
|
busybox \
|
||||||
|
wget
|
3
tests/integration/build_fail/context/Dockerfile
Normal file
3
tests/integration/build_fail/context/Dockerfile
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
FROM busybox
|
||||||
|
RUN this_command_does_not_exist
|
||||||
|
CMD ["sh"]
|
5
tests/integration/build_fail/docker-compose.yml
Normal file
5
tests/integration/build_fail/docker-compose.yml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
version: "3"
|
||||||
|
services:
|
||||||
|
test:
|
||||||
|
build: ./context
|
||||||
|
image: build-fail-img
|
1
tests/integration/build_labels/context/Dockerfile
Normal file
1
tests/integration/build_labels/context/Dockerfile
Normal file
@ -0,0 +1 @@
|
|||||||
|
FROM busybox
|
22
tests/integration/build_labels/docker-compose.yml
Normal file
22
tests/integration/build_labels/docker-compose.yml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
version: "3"
|
||||||
|
services:
|
||||||
|
test_build_labels_map:
|
||||||
|
build:
|
||||||
|
context: ./context
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
labels:
|
||||||
|
com.example.description: "Accounting webapp"
|
||||||
|
com.example.department: "Finance"
|
||||||
|
com.example.label-with-empty-value: ""
|
||||||
|
image: my-busybox-build-labels-map
|
||||||
|
command: env
|
||||||
|
test_build_labels_array:
|
||||||
|
build:
|
||||||
|
context: ./context
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
labels:
|
||||||
|
- "com.example.description=Accounting webapp"
|
||||||
|
- "com.example.department=Finance"
|
||||||
|
- "com.example.label-with-empty-value"
|
||||||
|
image: my-busybox-build-labels-array
|
||||||
|
command: env
|
60
tests/integration/build_labels/test_build_labels.py
Normal file
60
tests/integration/build_labels/test_build_labels.py
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from tests.integration.test_podman_compose import podman_compose_path
|
||||||
|
from tests.integration.test_podman_compose import test_path
|
||||||
|
from tests.integration.test_utils import RunSubprocessMixin
|
||||||
|
|
||||||
|
|
||||||
|
class TestBuildLabels(unittest.TestCase, RunSubprocessMixin):
|
||||||
|
def test_build_labels(self):
|
||||||
|
"""The build context can contain labels which should be added to the resulting image. They
|
||||||
|
can be either an array or a map.
|
||||||
|
"""
|
||||||
|
|
||||||
|
compose_path = os.path.join(test_path(), "build_labels/docker-compose.yml")
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.run_subprocess_assert_returncode([
|
||||||
|
podman_compose_path(),
|
||||||
|
"-f",
|
||||||
|
compose_path,
|
||||||
|
"build",
|
||||||
|
"test_build_labels_map",
|
||||||
|
"test_build_labels_array",
|
||||||
|
])
|
||||||
|
|
||||||
|
expected_labels = {
|
||||||
|
"com.example.department": "Finance",
|
||||||
|
"com.example.description": "Accounting webapp",
|
||||||
|
"com.example.label-with-empty-value": "",
|
||||||
|
}
|
||||||
|
|
||||||
|
out, _ = self.run_subprocess_assert_returncode([
|
||||||
|
"podman",
|
||||||
|
"inspect",
|
||||||
|
"my-busybox-build-labels-map",
|
||||||
|
"my-busybox-build-labels-array",
|
||||||
|
])
|
||||||
|
|
||||||
|
images = json.loads(out)
|
||||||
|
self.assertEqual(len(images), 2)
|
||||||
|
labels_map = images[0].get("Config", {}).get("Labels", {})
|
||||||
|
labels_array = images[1].get("Config", {}).get("Labels", {})
|
||||||
|
for k, v in expected_labels.items():
|
||||||
|
self.assertIn(k, labels_map)
|
||||||
|
self.assertEqual(labels_map[k], v)
|
||||||
|
self.assertIn(k, labels_array)
|
||||||
|
self.assertEqual(labels_array[k], v)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
self.run_subprocess_assert_returncode([
|
||||||
|
"podman",
|
||||||
|
"rmi",
|
||||||
|
"my-busybox-build-labels-map",
|
||||||
|
"my-busybox-build-labels-array",
|
||||||
|
])
|
9
tests/integration/build_secrets/Dockerfile
Normal file
9
tests/integration/build_secrets/Dockerfile
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
FROM busybox
|
||||||
|
|
||||||
|
RUN --mount=type=secret,required=true,id=build_secret \
|
||||||
|
ls -l /run/secrets/ && cat /run/secrets/build_secret
|
||||||
|
|
||||||
|
RUN --mount=type=secret,required=true,id=build_secret,target=/tmp/secret \
|
||||||
|
ls -l /run/secrets/ /tmp/ && cat /tmp/secret
|
||||||
|
|
||||||
|
CMD [ 'echo', 'nothing here' ]
|
22
tests/integration/build_secrets/docker-compose.yaml
Normal file
22
tests/integration/build_secrets/docker-compose.yaml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
version: "3.8"
|
||||||
|
|
||||||
|
services:
|
||||||
|
test:
|
||||||
|
image: test
|
||||||
|
secrets:
|
||||||
|
- run_secret # implicitly mount to /run/secrets/run_secret
|
||||||
|
- source: run_secret
|
||||||
|
target: /tmp/run_secret2 # explicit mount point
|
||||||
|
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
secrets:
|
||||||
|
- build_secret # can be mounted in Dockerfile with "RUN --mount=type=secret,id=build_secret"
|
||||||
|
- source: build_secret
|
||||||
|
target: build_secret2 # rename to build_secret2
|
||||||
|
|
||||||
|
secrets:
|
||||||
|
build_secret:
|
||||||
|
file: ./my_secret
|
||||||
|
run_secret:
|
||||||
|
file: ./my_secret
|
18
tests/integration/build_secrets/docker-compose.yaml.invalid
Normal file
18
tests/integration/build_secrets/docker-compose.yaml.invalid
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
version: "3.8"
|
||||||
|
|
||||||
|
services:
|
||||||
|
test:
|
||||||
|
image: test
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
secrets:
|
||||||
|
# invalid target argument
|
||||||
|
#
|
||||||
|
# According to https://github.com/compose-spec/compose-spec/blob/master/build.md, target is
|
||||||
|
# supposed to be the "name of a *file* to be mounted in /run/secrets/". Not a path.
|
||||||
|
- source: build_secret
|
||||||
|
target: /build_secret
|
||||||
|
|
||||||
|
secrets:
|
||||||
|
build_secret:
|
||||||
|
file: ./my_secret
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user