Compare commits

...

235 commits

Author SHA1 Message Date
768d4c8398 Удалить .woodpecker.yaml 2024-01-05 04:35:25 +03:00
0a4f338966 Обновить .woodpecker.yaml
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2024-01-05 04:34:48 +03:00
297c9da2d8 Обновить .woodpecker.yaml 2024-01-05 04:33:19 +03:00
f0abbb5ccd Обновить .woodpecker.yaml 2024-01-05 04:32:46 +03:00
fd426c9ceb Обновить .woodpecker.yaml 2024-01-05 04:31:51 +03:00
dfb174d4e4 Добавить .woodpecker.yaml 2024-01-05 04:31:32 +03:00
Josh Spicer
3ea4d6bbd7
Fix .zprofile is owned by root (#775)
* revert behavior of sourcing .profile in .zprofile

https://github.com/devcontainers/features/pull/736/files#diff-3e71c0a0669a0410f7dd0d8f2b83f3b6bf6b525d3eabd354f19f32822da669fcR460-R463

* add test

* increment version

* create empty .zprofile is not present, and fix test

* temporarily add back .profile to .zprofile (only if file did not exist)
2023-12-07 10:49:18 -08:00
Philipp Wagner
def3a41f57
Fix common-utils installation on RHEL (and friends) (#772)
* Fix indentation in common-utils/main.sh

* common-utils: Fix install error on RHEL

On RHEL (and derivatives) the installation of the common-utils feature
could fail if the feature ran before (i.e., `PACKAGES_ALREADY_INSTALLED`
is set) and if either `INSTALL_ZSH` is false, or zsh was installed
earlier and `ZSH_ALREADY_INSTALLED` is true.

In these cases the script the `package_list` is empty, and `dnf`
terminates with the following error message:

```
usage: dnf install [-c [config file]] [-q] [-v] [--version]
                   [--installroot [path]] [--nodocs] [--noplugins]
                   [--enableplugin [plugin]] [--disableplugin [plugin]]
                   [--releasever RELEASEVER] [--setopt SETOPTS]
                   [--skip-broken] [-h] [--allowerasing] [-b | --nobest] [-C]
                   [-R [minutes]] [-d [debug level]] [--debugsolver]
                   [--showduplicates] [-e ERRORLEVEL] [--obsoletes]
                   [--rpmverbosity [debug level name]] [-y] [--assumeno]
                   [--enablerepo [repo]] [--disablerepo [repo] | --repo
                   [repo]] [--enable | --disable] [-x [package]]
                   [--disableexcludes [repo]] [--repofrompath [repo,path]]
                   [--noautoremove] [--nogpgcheck] [--color COLOR] [--refresh]
                   [-4] [-6] [--destdir DESTDIR] [--downloadonly]
                   [--comment COMMENT] [--bugfix] [--enhancement]
                   [--newpackage] [--security] [--advisory ADVISORY]
                   [--bz BUGZILLA] [--cve CVES]
                   [--sec-severity {Critical,Important,Moderate,Low}]
                   [--forcearch ARCH]
                   PACKAGE [PACKAGE ...]
dnf install: error: the following arguments are required: PACKAGE
```

Fix the problem by running `dnf` only with a non-zero `package_list`.
2023-12-05 17:02:58 -08:00
Dev containers Bot
d53b9d1816
[Updates] Automated vendor dotnet-install script (#750)
* Automated dotnet-install script update

* Bump version

---------

Co-authored-by: github-actions <github-actions@github.com>
2023-11-14 09:56:03 -08:00
Dev containers Bot
710103a638
Automated documentation update (#738)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-10-30 10:20:06 -07:00
Oscar
7324b6d03c
Remove rebornix.Ruby extension (#737)
Remove the deprecated rebornix.Ruby extension from the list of installed extensions.
2023-10-30 10:16:28 -07:00
Samruddhi Khandale
d4ecc7be06
Update Features - Remove use of get_common_setting (#735) 2023-10-27 15:47:44 -07:00
Samruddhi Khandale
719901a1b4
[common-utils] Bug fix: zsh missing rc snippet (#736)
* [common-utils] Bug fix: zsp missing rc snippet

* condion rc snippet

* fix bug

* remove debugging step
2023-10-27 15:47:26 -07:00
Dev containers Bot
4c2c9f7b95
Automated documentation update (#732)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-10-23 16:14:35 -07:00
Lyon Till
e645120a39
Add PowerShell extension (#731)
* Add PowerShell extension

* Bump feature version
2023-10-23 16:08:27 -07:00
Richard Höchenberger
1155a9906b
Try connecting to Ubuntu keyserver on port 80 if default HKP port fails (#722)
* Try Ubuntu keyserver on port 80 if default HKP port fails

Closes #719
Closes #717

* Bump feature versions

---------

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>
2023-10-17 23:45:04 +00:00
Samruddhi Khandale
36a3604b90
[Python] - Support 3.12 (#726) 2023-10-17 15:05:01 -07:00
Samruddhi Khandale
4fca96b5e8
[Docker-in-docker] Updates docker-init scripts (#715)
* updates

* version bump
2023-10-05 11:27:01 -07:00
Jan-Marco Edelmann
0d7ad7c5fc
Configure npm proxy when proxy environmentals exist (#712) 2023-10-04 15:09:35 -07:00
Alexander Smolyakov
90a9b1d604
[terraform] Update retry logic to handle DNS-related errors more gracefully (#713)
* [terraform] Update retry logic

- Add `dnsutils` package to dependencies
- Update retry logic to handle DNS-related errors more gracefully

* Update install.sh

* Bump version
2023-10-04 10:00:11 -07:00
Luciana Abud
c3f9105048
Remove deprecated Python settings (#625)
* Remove deprecated Python settings

* No longer install Python linters and formatters

* Revert "No longer install Python linters and formatters"

This reverts commit 57c7bec14d.

* Bump minor version
2023-10-02 08:59:25 -07:00
Samruddhi Khandale
04cb7d1e79
Docker-in-docker: Updates docker-init with "pkill" (#711)
* Docker-in-docker: Updates docker-init with "pkill"

* pkill only if container didn't start at first

* pkill with condition

* add back sudo_if
2023-09-29 12:02:54 -07:00
Samruddhi Khandale
cf92754bf4
Automated documentation update (#709)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-09-29 11:50:09 -07:00
Steven
803ec6e0e5
Bump the dotnet version after a script update (#707)
* Bump the dotnet version after a script update

* Forgot to add file

* Keep 4 spaces indentation
2023-09-28 10:50:20 -07:00
Samruddhi Khandale
0599c63f8f
[Updates] Automated vendor dotnet-install script (#698)
* Automated dotnet-install script update

* version bump

---------

Co-authored-by: github-actions <github-actions@github.com>
2023-09-28 10:08:39 -07:00
Samruddhi Khandale
3aad9a72f4
Terraform - Adds licensing information (#697)
* Terraform - Adds licensing information

* Update src/terraform/NOTES.md

Co-authored-by: Brigit Murtaugh <brigit.murtaugh@microsoft.com>

---------

Co-authored-by: Brigit Murtaugh <brigit.murtaugh@microsoft.com>
2023-09-28 09:59:04 -07:00
Masahiro Wada
243671eece
Enhancements in CUDA Support (#699)
* add cuda tookit installing support

* add nvcc installing support

* add libcudnn8-dev installing support

* add new cuda versions adn cudnn versions

* add specificaitons of new option

* remove installNvcc

installNvcc process is included in installToolkit

* add tests for new nvidia-cuda options

* fix wrong scenario name

* Revert "add specificaitons of new option"

This reverts commit 0dcdb92406.

README.md should be generated by CI workflow.

* make cudnn-dev installation isolated

* dump minor version to 1.1.0
2023-09-27 12:17:31 -07:00
Alexander Smolyakov
0d2fc3ad5b
[python] Change the sudo_if function to avoid issues with Bash (#694)
* [python] Updated `sudo_if` function

- Remove double quotes to avoid issues with string tokenization

* Add test scenario

* Revert "Add test scenario"

This reverts commit 9e62a3797a.

* Update `jupyterlab git` package name

* Bump feature version

* Test: Install jupyterlab under root user

* Refactor changes

* Bump patch version

* Address review points
2023-09-27 11:51:26 -07:00
Pablo Ulloa
e7f7d194d6
[common-utils] fix bug when user home is custom by base docker (#703)
* [common-utils] fix bug when user home is custom by base docker

* bumped minor version

* reduced conditions to improve readability
2023-09-27 11:45:29 -07:00
Pablo Ulloa
9852ca8888
[java] fix version regex to support graalce jdk 21 (#701)
* [java] fixed feature test scenario check

* [java] support for non conentional version

* Update src/java/install.sh to not include whitespaces

Co-authored-by: Samruddhi Khandale <samruddhikhandale@github.com>

* bumped patch version

---------

Co-authored-by: Samruddhi Khandale <samruddhikhandale@github.com>
2023-09-27 09:26:53 -07:00
Steven
3a22c41940
Configure environment for update-dotnet-install-script.yml (#693) 2023-09-19 09:58:33 -07:00
Samruddhi Khandale
f92f7ba7ae
[common-utils]: Bug fix: Install zsh on an image previously built with "installZsh:false" (#649)
* [common-utils]: Bug fix: Installs zsh on an image built with installZsh:false

* version bump

* nit: fix merge conflicts

* Version bump
2023-09-14 09:05:50 -07:00
Samruddhi Khandale
97eea5deee
[Go] Update proposals for the "version" option (#654)
Update devcontainer-feature.json
2023-09-13 08:42:41 -07:00
Samruddhi Khandale
a771e8cb42
[Docker-in-docker] Support bookworm (#661)
* [Docker-in-docker] Support bookworm

* Update devcontainer-feature.json
2023-09-11 11:32:53 -07:00
Samruddhi Khandale
8ad7c749b3
Automated documentation update (#688)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-09-11 11:28:49 -07:00
Steven
96c1eea40f
Use dotnet-install.sh in .NET feature (#628)
* Use dotnet-install.sh in .NET feature

* Use latest.version files

* Cleanup runtime args

* Use latest.version files in tests as well

* Improve tests, remove code duplication

* Add stderr helper

* Validate version inputs

* Use suggested description

Co-authored-by: Samruddhi Khandale <samruddhikhandale@github.com>

* Shorter version description

Co-authored-by: Samruddhi Khandale <samruddhikhandale@github.com>

* Shorter version description

Co-authored-by: Samruddhi Khandale <samruddhikhandale@github.com>

* Clean up apt lists

* Verify 7.0 is latest

* Fix PATH, add test for .NET global tools

* Include a copy of dotnet-install.sh in the Feature

* Configure useful env variables

* Use stringly typed booleans

* Keep imperative writing style in option hints

* Update maintainers

Co-authored-by: Samruddhi Khandale <samruddhikhandale@github.com>

* Move dotnet-install.sh into a vendor directory

* Refactor variables

* Amend

* Amend 2

* Use default options from devcontainer-feature.json

* Add back variables

* Fix shellchek warning in fetch_latest_sdk_version

* Inline install_version function

* Fix ShellCheck warnings

* Improve CSV parsing

* Default to latest when configuring an empty version

* Add support for runtime-only configurations

* Move 'none' check higher up

* Deduplicate helper functions, sort into files

* Address the user more directly in NOTES

* Remove unnecessary defaults

* Replace feature -> Feature

Co-authored-by: Samruddhi Khandale <samruddhikhandale@github.com>

* Add update-dotnet-install-script workflow

* Apply suggestions from code review

Co-authored-by: Samruddhi Khandale <samruddhikhandale@github.com>

* Don't skip ci for automated script update

---------

Co-authored-by: Samruddhi Khandale <samruddhikhandale@github.com>
2023-09-11 11:16:24 -07:00
eitsupi
038bed3d58
ci: remove ubuntu:bionic from test matrixes (#677)
ci: remove ubuntu:bionic from test matrixes
2023-08-29 09:32:46 -07:00
Samruddhi Khandale
96bff00970
Automated documentation update (#676)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-08-28 15:15:43 -07:00
eitsupi
95a169b9ef
[node] Install the latest version of nvm by default (#673)
feat(node): install the latest nvm by default
2023-08-28 14:26:30 -07:00
naturedamends
0668db5ede
Commonutils: chown: cannot access '/home/vscode/.zshrc': No such file or directory (#662)
* Update main.sh

* Update devcontainer-feature.json

* Test install as non root user.

---------

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>
2023-08-25 16:39:32 -07:00
Samruddhi Khandale
0cf690ee14
[docker in docker] Adds retries for docker daemon startup and cgroup nesting (#669)
* adds retry logic

* adds stress test workflow

* Adds cgroup retries

* update workflow

* move sleep cmd

* update test

* cleanup
2023-08-24 12:31:40 -07:00
nyuyuyu
a08434f2b1
[Rust] Remove mutantdino.resourcemonitor extension (#665)
* Remove `mutantdino.resourcemonitor` extension

* Bump version

* Revert "Bump version"

This reverts commit e9c514911d.

* Bump version
2023-08-24 09:38:40 -07:00
Bulat Khusnimardanov
71ac2021e1
Enhancing Terraform Feature Stability (#657)
* Added fallback method to retrieve cosign version

* Update src/terraform/install.sh

Co-authored-by: Samruddhi Khandale <samruddhikhandale@github.com>

* Remove get_cosign_latest_version function

---------

Co-authored-by: Samruddhi Khandale <samruddhikhandale@github.com>
2023-08-21 17:31:20 -07:00
Samruddhi Khandale
a4b31f314f
[docker-in-docker] Reverts the retry logic (#659)
* Update install.sh

* [docker-in-docker] Update retry logic

* revert the retry logic!
2023-08-18 16:01:50 -07:00
Samruddhi Khandale
9fd5daf06b
Automated documentation update (#656)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-08-16 11:43:06 -07:00
Samruddhi Khandale
c58b614202
Azure-cli: Revert temporary fix which installed az with python (#629) 2023-08-16 11:38:49 -07:00
Samruddhi Khandale
1d1a23625d
Ruby Feature [bug fix] : Fails if the dev container has the same ruby version installed (#609)
* Ruby Feature [bug fix] : Fails if the dev container has the same ruby version installed

* add comment

* remove scenario
2023-08-16 11:38:35 -07:00
Samruddhi Khandale
f90cb26c7f
Common-utils: Fixes "No package jq available" errors for CentOS (#644)
* add checks for "jq"

* install epel-release if necessary

* clean up epel-release post installation of "jq"
2023-08-14 16:12:47 -07:00
Samruddhi Khandale
8b6f088256
Automated documentation update (#650)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-08-11 16:17:50 -07:00
naturedamends
be082b0ef5
Common utils: Add config to remove zsh rc files from (#614)
* Add config to remove zsh rc files from common-utils.

* Bump version and add config to install script.

* Checks preventing excess writing to .zshrc.

* Change devcontainer feature option name.

* Coding standards.

* Favour adding feature via config 

and default to overriding .zshrc with dev-container default template.

* Update devcontainer-feature.json

* Update devcontainer-feature.json

* Update src/common-utils/devcontainer-feature.json

Co-authored-by: Samruddhi Khandale <samruddhikhandale@github.com>

* Update src/common-utils/devcontainer-feature.json

Co-authored-by: Samruddhi Khandale <samruddhikhandale@github.com>

* Testing for using devcontainer .zshrc template file.

* Coding standards.

* Coding standards.

* Update configure_zsh_as_default_shell_no_template.sh

* Grammar in configure_zsh_as_default_shell.sh

* Testing accounts for marked file cache  (#4)

* Account for mark file in testing.

* Remove some debugging and tests back

* Add back tests?

* Update configure_zsh_no_template.sh

---------

Co-authored-by: Samruddhi Khandale <samruddhikhandale@github.com>
2023-08-11 16:01:57 -07:00
Shikanime Deva
9e75db9a1d
Avoid unexpected shell expansion (#645)
* Avoid unexpected shell expansion

* Add install Node with ZSH as default test

* Fix LTS only work on >bionic

* Bump Node feature version

* Remove huge universal image on scenarios
2023-08-09 16:20:27 -07:00
Samruddhi Khandale
f2594c5cc8
Automated documentation update (#642)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-08-07 16:29:54 -07:00
Samruddhi Khandale
bbb24d10d4
Docker-in-docker: Add retries to the docker-init script until docker daemon starts (#637)
* Docker-in-docker: Add retries until docker daemon starts

* address comments
2023-08-07 15:59:58 -07:00
Tom Palmer
29859aff28
Fix 2 instances of a typo in the desktop-lite NOTES and README (#640)
* Amend 'is installed is' to 'installed is'.

* Undo typo fix from README

Co-authored-by: Samruddhi Khandale <samruddhikhandale@github.com>

---------

Co-authored-by: Samruddhi Khandale <samruddhikhandale@github.com>
2023-08-07 15:12:13 -07:00
Krikchai Pongtaveewould
685fa2e0f1
Fix: common-utils configureZshAsDefaultShell option not working on alpine linux image (#557)
* alpine defaultZsh fix

* common-utils: replace pam.d/chsh permission with `sufficient`

* common-utils: revert match auth sufficient

* common-utils: append auth string instead of replacing a whole file

* fix grep 2nd param

* fix: line checking condition
2023-08-02 15:12:14 -07:00
Samruddhi Khandale
836ea1e9fa
Automated documentation update (#627)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-07-26 14:43:43 -07:00
Samruddhi Khandale
ea2d79070e
Azure-cli - Temporary quick fix for jammy (ARM) (#626) 2023-07-21 17:37:10 -07:00
Samruddhi Khandale
7fcec6e7c9
Fix: Docker-in-docker for python - Arm64 (#618)
Fix: Docker-in-docker for python:3.11 - Arm64
2023-07-19 08:50:22 -07:00
Samruddhi Khandale
0e8940abea
Automated documentation update (#610)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-07-11 12:50:29 -07:00
Samruddhi Khandale
07693965d7
Nvidia-cuda: Update notes regarding gpu enablement (#608)
* Nvidia-cuda: Update notes regarding gpu enablement

* use GPU hostRequirements instead

* nit

* use gpu:optional instead
2023-07-11 11:16:23 -07:00
Kazuma Watanabe
c4ffeebdac
Pin version of TFLint's GPG key URL (#605) 2023-07-06 10:23:36 -07:00
Samruddhi Khandale
300814be97
Dotnet: Fix Feature failures on ubuntu:jammy (when installing using apt) (#590)
* fix several bugs

* fix test: .NET is now installed from ubuntu feeds

* add comment ; use dev containers image

* address comments

* revert debugging cmd

* fix test for bookworm
2023-06-29 15:14:11 -07:00
Samruddhi Khandale
8a51aa9066
Automated documentation update (#602)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-06-29 15:08:34 -07:00
Rafael Mendonça França
ef76ff97b6
Change Ruby extension to ruby-lsp (#566)
This is the extension that is recommended in the VSCode documentation now.

https://code.visualstudio.com/docs/languages/ruby
2023-06-29 15:00:56 -07:00
dependabot[bot]
b6dbe7051c
Bump mpmath from 1.2.1 to 1.3.0 in /test/oryx/sample-python (#554)
Bumps [mpmath](https://github.com/fredrik-johansson/mpmath) from 1.2.1 to 1.3.0.
- [Release notes](https://github.com/fredrik-johansson/mpmath/releases)
- [Changelog](https://github.com/mpmath/mpmath/blob/master/CHANGES)
- [Commits](https://github.com/fredrik-johansson/mpmath/compare/1.2.1...1.3.0)

---
updated-dependencies:
- dependency-name: mpmath
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-28 16:16:30 -07:00
Samruddhi Khandale
610286c369
Automated documentation update (#596)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-06-28 14:17:06 -07:00
Melissa Weber Mendonça
972fdffa71
Add instructions to set up port forwarding on devcontainer.json file (#593) 2023-06-28 09:17:04 -07:00
Josh Spicer
ccce957d7e
Azure CLI: Compatibility with Debian bookworm (#578)
* add flag

* try to install via apt version of pipx (will only work on bookworm)

* _REMOTE_USER aware

* dont change more than you need to,josh

* increment azure-cli minor version (v1.1.0)

* install globally

* make sure env variables are in scope
2023-06-27 14:31:18 -07:00
Samruddhi Khandale
de40074875
Automated documentation update (#587)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-06-23 16:16:30 -07:00
Josh Spicer
d934503a05
Terraform: Add cosign integrity check for TFLint (#586)
* add cosign integrity check for tflint

* fallback to gpg verification
2023-06-21 11:13:46 -07:00
Imamuzzaki Abu Salam
2258fcb040
feat(rust): add up to version 1.70 options (#579) 2023-06-20 10:34:07 -07:00
Samruddhi Khandale
2fb386db11
Automated documentation update (#585)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-06-19 11:33:35 -07:00
Josh Spicer
931262d20c release terraform 2023-06-19 18:24:44 +00:00
Josh Spicer
ee9f0bfbf0
Temporaily pin TFLint to 0.46.1 (#583)
temporaily pin TFLint to 0.46.1

https://github.com/devcontainers/features/issues/581
2023-06-19 11:23:49 -07:00
Josh Spicer
367308c736
Add Debian Bookworm as a test base image (#575)
test against debian bookworm
2023-06-16 14:31:40 -07:00
Samruddhi Khandale
852f1f0567
Automated documentation update (#563)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-05-31 11:55:51 -07:00
Shunya Hayashi
cfae3b0f0d
update go tools (#559)
* update go tools

* update link

* add unit tests for confirm installation

* fix path install gotests

* fix bump the minor version
2023-05-31 08:53:50 -07:00
Raymond
b48d8700ff
Update NOTES.md (#534)
* Update NOTES.md

#531: Quick document update about UID & GID using 1000 in devcontainer base images.

* Update src/common-utils/NOTES.md

@samruddhikhandale The common-utils Feature is used by most of the dev container images, along with the base image. Can we update the text?

Co-authored-by: Samruddhi Khandale <samruddhikhandale@github.com>

* Update src/common-utils/NOTES.md

@samruddhikhandale

Co-authored-by: Samruddhi Khandale <samruddhikhandale@github.com>

---------

Co-authored-by: Samruddhi Khandale <samruddhikhandale@github.com>
2023-05-22 12:23:23 -07:00
Stephen A. Imhoff
1869e5931c
Create .config directory in common-utils (#547)
* Add test case for mounted subdirectory.

* Correct some trailing whitespace.

* Correct variable name to better reflect status as user home path.

* Add config directory creation.

* Remove extra debug line.

* Bump feature version.

* Mount host user home directory as "subdirectory"

* Correct test naming, run test in explicit bash shell.
2023-05-10 10:04:16 -07:00
Samruddhi Khandale
4420cd5d27
Automated documentation update (#543)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-05-09 13:52:06 -07:00
M. R
4312340798
Add support for skipping docker-compose v1 operations during Docker feature install script (#533)
* Add support for skipping docker-compose operations

* Move changes from auto-generated files to templates and bump version

* Add test

* Add test conditions

* Add test conditions for docker-outside-of-docker

* install.sh set -x for debugging

* set -x

* Move compose-switch check in docker-outside-of-docker test

* Put into correct test

* Test for correct path
2023-05-02 12:00:45 -07:00
Raymond
b16ff1efb7
Update devcontainer-feature.json (#539)
#535 update the patch version to 2.0.9
2023-05-01 08:38:01 -07:00
Raymond
e2b3b48bc5
Update devcontainer-feature.json (#535)
#531 Modify proposed UID & GID so as not to conflict with base image.
2023-05-01 08:37:43 -07:00
Felix Altenberg
f52ff611c5
Adds httpProxy option to Python Feature (#532)
* Adds httpProxy option to Python Feature
This option allows GPG to use a HTTP proxy to fetch keys from remote keyservers

* Updating minor version

Co-authored-by: Samruddhi Khandale <samruddhikhandale@github.com>

* Fixes minor formatting error

---------

Co-authored-by: Samruddhi Khandale <samruddhikhandale@github.com>
2023-04-28 13:38:25 -07:00
Samruddhi Khandale
fad03b19d4
Oryx - Switch to .NET 7 (#522)
* Oryx - Switch to .NET 7

* fix test ; add test

* fix test - back compat
2023-04-18 14:37:51 -07:00
Samruddhi Khandale
2237731474
Automated documentation update (#521)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-04-14 13:48:25 -07:00
Alexander Smolyakov
8d3e9aca9d
[features/conda] Address CVE-2023-0286, CVE-2023-23931, and CVE-2022-40897 vulnerabilities (#518)
* [features/conda] Address CVE-2023-0286, CVE-2023-23931, and CVE-2022-40897 vulnerabilities

- Update `install.sh` to install updates for `cryptography` and `setuptools`  packages
- Add tests to verify `cryptography` and `setuptools`  packages version

* Bump feature version
2023-04-06 10:02:49 -07:00
Samruddhi Khandale
74959ec149
Automated documentation update (#517)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-04-05 16:06:27 -07:00
Ryan Campbell
585ee2a42c
Removing forced gid 999 for docker (#515)
* Removing forced gid 999 for docker

* version bump

---------

Co-authored-by: Ryan Campbell <rycampbe@microsoft.com>
Co-authored-by: Samruddhi Khandale <samruddhikhandale@github.com>
2023-04-05 12:33:00 -07:00
Felipe Santos
7f605b9452
Fix several issues with docker-outside-of-docker (#443)
* Fix several issues with docker-outside-of-docker

* Add initial tests and bump version

* Add two tests

* Fix docker buildx conflict

* Fix possible test issue

* Add tests for moby

* Add buildx test to init

* Fix inconsistency

* Many fixes and improvements

* Make dockeDashCompose v2 by default
2023-04-05 11:21:36 -07:00
Samruddhi Khandale
f0dd470ba8
Automated documentation update (#512)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-04-04 10:05:12 -07:00
Josh Spicer
2952d87f1d
add a postCreateCommand to git-lfs Feature (#511)
* add a postCreateCommand to git-lfs Feature

* debug passing locally but not in CI

* update scenario

* add GIT_LFS_SKIP_SMUDGE=1 to prevent fetching lfs arifacts in github actions

* arguments should be booleans

* move example repo to devcontainers org

* place script literally anywhere other than /tmp
2023-04-04 06:47:04 -07:00
Samruddhi Khandale
1118b992d9
Ruby: Fix failures - omit "ruby-debug-ide" (#505)
* Ruby: Fix failures on debian image due to ruby-debug-ide

* omit
2023-03-28 16:05:17 -07:00
Jacob Hummer
0e079baaf7
Add contributing document (#488)
* Create CONTRIBUTING.md

* Direct questions to slack channel

Co-authored-by: Brigit Murtaugh <brigit.murtaugh@microsoft.com>

* Use "dev containers" and "Features"

Apparently devcontainers is two words, and apparently features is a proper noun? I guess 🤷‍♂️

* Prettier formatting

I used https://prettier.io/playground/ since I was editing in the GitHub web editor

* Clarify to "only accept improvements and bug fixes"

Co-authored-by: Samruddhi Khandale <samruddhikhandale@github.com>

* Be more explicit about custom features

Co-authored-by: Samruddhi Khandale <samruddhikhandale@github.com>

* Add link to CLI test docs

* Add semver step in guide

* More specificity in link text

https://github.com/devcontainers/features/pull/488#discussion_r1137819187

* Add CONTRIBUTING.md link in readme

---------

Co-authored-by: Brigit Murtaugh <brigit.murtaugh@microsoft.com>
Co-authored-by: Samruddhi Khandale <samruddhikhandale@github.com>
2023-03-23 16:07:08 -07:00
Samruddhi Khandale
e7e4aa8a98
Automated documentation update (#490)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-03-14 09:17:38 -07:00
Daniel Ciborowski
d4c3fefc4a
Add pytest to Python Feature (#487)
* Update install.sh

* Update install_additional_python.sh

* Update install_os_provided_python.sh

* Update install_via_oryx.sh

* Update test.sh

* Update devcontainer-feature.json
2023-03-14 08:23:28 -07:00
Eljo George
1449f416a0
Remove duplicate env var sourcing for codespaces (#481)
* Remove duplicate env var sourcing for codespaces
2023-03-10 12:27:28 -08:00
Josh Spicer
adf7240a7c
oryx-supported-platforms (#482) 2023-03-10 08:50:32 -08:00
Samruddhi Khandale
5d6f1ae9b9
Automated documentation update (#479)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-03-08 15:40:30 -08:00
Samruddhi Khandale
de1e634a67
Docker fix - BuildKit is enabled but the buildx component is missing or broken (#478)
* Docker fix - BuildKit is enabled but the buildx component is missing or broken

* nit

* fix test
2023-03-08 15:30:59 -08:00
Samruddhi Khandale
fe449253f1
Automated documentation update (#475)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-03-07 11:43:06 -08:00
ksaito1125
3e6ee966ba
Terraform: Add proxy setting (#435) (#451)
* Terraform: Add proxy setting (#435)

* Terraform: Remove unused variable GPG_OPTS (#435)

* Terraform: Increment minor version (#435)

* Update src/terraform/install.sh

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>

* Add feature option

* Update src/terraform/devcontainer-feature.json

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>

* Update src/terraform/devcontainer-feature.json

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>

* Update src/terraform/devcontainer-feature.json

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>

* Terraform: Change environment variables to upper case (#435)

* Terraform: Use HTTP_PROXY as the default for connecting to keyservers (#435)

* Update src/terraform/install.sh

Co-authored-by: Samruddhi Khandale <samruddhikhandale@github.com>

---------

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>
Co-authored-by: Samruddhi Khandale <samruddhikhandale@github.com>
2023-03-06 08:51:35 -08:00
Samruddhi Khandale
3cc059ea8a
Automated documentation update (#462)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-03-01 15:54:58 -08:00
Brett Cannon
4b7efebea1
Turn off linting by default in VS Code for Python (#449)
* Turn off linting by default in VS Code for Python
Linting is on by default if you specify the paths to any linters, so the previous settings would turn on **all** linters.

Also drop linters that don't see much use.

* Fix tests

* Revert all changes

* Remove paths to under-utilized tools and turn off all linting by default

* Bump the version number
2023-03-01 15:29:11 -08:00
Akihiro Nagai
83c6103db2
Add pnpm in Node (#450)
* Add pnpm in Node

* pnpm from npm

* Restore README.md

* Update install.sh

* Update tests
2023-02-27 09:12:21 -08:00
Samruddhi Khandale
d84e46be47
"Update Documentation" workflow - use gh api to create a documentation PR (#459) 2023-02-22 12:23:22 -08:00
github-actions[bot]
8d3685e09f
Automated documentation update (#455)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-02-15 12:01:23 -08:00
Stefan Drzazga
900cbfc1f9
Add sentinel to terraform feature (#452)
* Introducing Sentinel installation

* Modifying docs for sentinel

* Modifying tests for sentinel

* Revert "Modifying docs for sentinel"

This reverts commit 818894b22f.

* Modifying docs for sentinel

* Fixing duplication issue for sentinel url

* Update src/terraform/install.sh

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>

* Increase minor version

---------

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>
2023-02-15 11:59:31 -08:00
Samruddhi Khandale
4a9929f964
kubectl-helm-minikube: Allow none (#442) 2023-02-07 11:45:48 -08:00
Samruddhi Khandale
36d7664eba
PHP: Allow 'version:none' (#439)
* PHP: Allow 'version:none'

* fix tests
2023-02-07 09:52:33 -08:00
Samruddhi Khandale
c997f9af69
Rust - Clean up unwanted settings (#434)
* Rust - Clean up unwanted settings

* address comments
2023-02-03 09:27:17 -08:00
github-actions[bot]
6bf4a7dbec
Automated documentation update (#431)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-01-30 11:42:51 -08:00
Ross Smith
7763e0b7db
Install PowerShell Modules (#427)
* InstallBicep

* Add test for InstallBicep

* Install pwsh Modules

* Script rename

* Add -Command to test

* Check version

* Install the module for all users

* Adding terminating lines to scripts

* Update src/powershell/install.sh

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>

* Update src/powershell/install.sh

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>

* Removed comments in Readme

* Remove Bicep from PowerShell install

* Increased version number

* Update Minor version rather than patch

---------

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>
2023-01-30 11:29:13 -08:00
Levin Winter
fbdc4556d5
[common-utils] Fix nonempty .bashrc being restored (#421)
* [common-utils] Fix nonempty .bashrc being restored
The user's dotfiles shall only be restored to their defaults if they do
not exist or are empty. A missing negation caused the files to be
overwritten even when they were nonempty.

* [common-utils] Bump patch version after fix
Go from 2.0.7 to 2.0.8 because of backwards-compatible fix.
2023-01-25 15:57:31 -08:00
Josh Spicer
258d5029a5
Republish all Features to add repo tags (#422)
republish all features to add repo tags
2023-01-25 10:24:25 -08:00
dylhack.dev
676e824e92
features/nix: remove PGP check (#414)
* nix: remove PGP check

* fix issues
2023-01-24 10:28:54 -08:00
github-actions[bot]
3a579894a0
Automated documentation update (#417)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-01-23 15:21:02 -08:00
Pamela Fox
bebf87e33c
Add more detail to note about architecture (#416)
* Add more detail to note about architecture

* Update src/docker-in-docker/NOTES.md

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>

* Update src/docker-in-docker/NOTES.md

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>
2023-01-23 15:18:50 -08:00
Samruddhi Khandale
7a3a9c5fca
Php: Auto configure if a three part version is not provided (#406)
* Php: Auto configure if a three part version is not provided

* fix test

* update checks

* Bump version
2023-01-20 09:22:39 -08:00
github-actions[bot]
24b33c5f79
Automated documentation update (#410)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-01-18 13:42:35 -08:00
Tobias Gesellchen
d78a153492
Java: add Apache Ant (#409)
* Java: add Apache Ant

* Update src/java/devcontainer-feature.json

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>

* revert the changes in README.md

* Add tests for Java/Ant

* Fix Java feature version

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>
2023-01-18 13:24:10 -08:00
github-actions[bot]
f7314671e1
Automated documentation update (#405)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-01-17 09:46:27 -08:00
Samruddhi Khandale
58b8fe093d
Fix typos in comments / *.md (#396) 2023-01-17 09:34:53 -08:00
Stephan
79588ef3da
checkout action update (#404)
- updated the action checkout from v2 to 3 as required by action warning
2023-01-17 09:18:13 -08:00
Stephen A. Imhoff
1726222515
CommonUtils - ensure home directory exists. (#398)
* CommonUtils - ensure home directory exists.

* Only create non-root home directory

Root directory will always exist.

* Bump version
2023-01-13 11:05:53 -08:00
Samruddhi Khandale
74dd2710dc
Git: Use sysconfdir=/etc for git built from source (#395)
* Git: Adds a new 'addGitConfigSymlink' option

* Use sysconfdir
2023-01-11 11:02:28 -08:00
Samruddhi Khandale
e67f4dc0fd
Common-utils: Fix build failures for alpine 3.14 & 3.15 (#393)
* Common-utils: Fix build failures for alpine 3.14 & 3.15

* version bump
2023-01-10 15:09:56 -08:00
github-actions[bot]
c8f5c3cbee
Automated documentation update (#394)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-01-10 13:59:07 -08:00
eitsupi
7e32db56c0
[common-utils] Fix permission of scripts in containers (#388)
* fix permission in containers

* add test

* bump version

* more tests

* update tests

* Update test/common-utils/devcontainer-info/Dockerfile

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>

* Update test/common-utils/scenarios.json

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>

* Update scenarios.json

* Update devcontainer-info.sh

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>
2023-01-10 13:50:09 -08:00
Samruddhi Khandale
59fa3e3c21
Conda: Update 'certifi' due to CVE-2022-23491 (#383) 2023-01-09 14:49:43 -08:00
Samruddhi Khandale
04143e31ff
Options: Switch from 'enum' to 'proposals' (#382) 2023-01-09 14:48:41 -08:00
Mark Phippard
a9a7a25d60
Install gawk RPM (#380)
* Install gawk RPM

This script requires awk and it may not be available on a
minimal distro like Mariner

* Bump version number
2023-01-05 13:21:34 -08:00
Marko Bausch
c546f4bf8c
desktop-lite: fixed qemu container (#370)
* desktop-lite: fixed qemu container

* bump version for desktop-lite
2023-01-05 09:27:12 -08:00
Samruddhi Khandale
ef192bf467
PHP: Fix build failures for 'ubuntu:bionic' (#378)
* PHP: Fix build failures for 'ubuntu:bionic'

* update VERSION
2023-01-04 14:59:24 -08:00
Julien Boudry
8f7eec80d4
[PHP] Enable Mbstring (#371)
Mbstring is such a popular PHP extension that it is used everywhere and most libraries don't work without it. It can be compiled directly with PHP.
The official Docker images of PHP include it.
2023-01-04 13:12:53 -08:00
github-actions[bot]
2c646ed9fe
Automated documentation update (#377)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2023-01-04 11:53:48 -08:00
Samruddhi Khandale
eef35a4399
Rename "docker-from-docker" to "docker-outside-of-docker" (#373)
* Rename to "docker-outside-of-docker"

* rename test folder
2023-01-04 11:52:05 -08:00
Josh Spicer
6c76a7b488
Add validate workflow (#369)
* add validate workflow

* make typo to test 3c61c88

* remove unneeded if

* fix typo

* better names

* Update validate-metadata-files.yml
2023-01-03 14:52:56 -08:00
Samruddhi Khandale
dbf069a5db
Common-utils : Version bump (#367)
Common-utils - Version bump
2022-12-27 10:50:33 -08:00
Samruddhi Khandale
29babe4245 fix test 2022-12-27 18:35:13 +00:00
github-actions[bot]
f9de0e43f8
Automated documentation update (#368)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2022-12-27 12:42:28 -05:00
Josh Spicer
19bc8bb633
OS support in Feature NOTES.md (#366)
* https://github.com/devcontainers/features/issues/360

* omit from common utils
2022-12-27 12:27:57 -05:00
github-actions[bot]
80ed2fbc30
Automated documentation update (#365)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2022-12-27 09:51:25 -05:00
Josh Spicer
00dd4f4a19
remove unused buildArg in java Feature 2022-12-27 14:49:40 +00:00
Josh Spicer
592fdc8177
typo in 'dotnet' Feature schema 2022-12-27 09:36:51 -05:00
Josh Spicer
5fb5c388b5
typo 2022-12-27 09:32:34 -05:00
eitsupi
b6921f9b9f
feat(common-utils): Support the new path of meta.env file and the new field for saving source revisions (#359)
* support the new path of meta.env

* support the new field for the image revision

* minor formatting
2022-12-27 08:25:33 -05:00
Samruddhi Khandale
b9bfe406d2
Update GPG_KEY_SERVERS: Remove :80 from Ubuntu Keyserver (#354)
* Update GPG_KEY_SERVERS: Remove `:80` from Ubuntu Keyserver

* Fix ruby tests
2022-12-21 12:15:24 -08:00
Samruddhi Khandale
48678001d1
Terraform: Update GPG_KEY_SERVERS (#353)
* Terraform: Update GPG_KEY_SERVERS

* add check
2022-12-21 09:11:10 -08:00
Josh Spicer
42e5a013cc
common-utils 2.0.2 (#350)
Will release staged change: fede405549
2022-12-19 12:19:46 -05:00
github-actions[bot]
2472653c31
Automated documentation update (#351)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2022-12-19 09:11:02 -08:00
github-actions[bot]
e46fe0eb34
Automated documentation update (#349)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2022-12-19 11:27:18 -05:00
Mark Phippard
fede405549
Add support for mariner (#344) 2022-12-19 11:25:32 -05:00
zephyros-dev
9af65a01c7
docs: add bind mount docs for docker from docker (#343)
Co-authored-by: ptn <ptn@cct-technology.com>
2022-12-19 11:24:59 -05:00
eitsupi
7867e008c1
Fix /etc/bash.bashrc generated by common-utils (#342)
* Fix /etc/bash.bashrc generated by common-utils

* bump version
2022-12-19 11:23:05 -05:00
Samruddhi Khandale
2af02c198a
Git - Bug Fix: Feature fails with "ppa:false" for "buster" & "bullseye" (#340) 2022-12-16 16:08:37 -08:00
Samruddhi Khandale
e46c73de74
Git - Bug Fix: Feature fails with "ppa:false" for bionic & jammy (#339) 2022-12-16 14:21:05 -08:00
github-actions[bot]
a3dc31d31f
Automated documentation update (#338)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2022-12-16 11:33:40 -08:00
Chuck Lantz
bf058dc494
Multi-distro support for common script, refactor, fixes (#326) 2022-12-16 09:47:21 -08:00
Samruddhi Khandale
7fa90110d7
Git: Build from source with USE_LIBPCRE (#331) 2022-12-13 14:09:16 -08:00
github-actions[bot]
baf47e22b0
Automated documentation update (#332)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2022-12-13 10:59:48 -08:00
Pierre-Emmanuel Mercier
84f3e62d1c
Add TFSec and Terraform Docs to Terraform features (#327)
* Add TFSec and Terraform Docs

* PR Review

* code review
2022-12-13 10:58:22 -08:00
github-actions[bot]
7b009e661f
Automated documentation update (#328)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2022-12-09 14:10:41 -08:00
Jacob Woffenden
aae9de7ebc
Change default shell if installing ZSH (#325)
* Added new option to configure zsh as default shell
Added test scenario
Bumped feature version

* Update test/common-utils/scenarios.json

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>

* Update src/common-utils/devcontainer-feature.json

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>

* Update test/common-utils/configure_zsh_as_default_shell.sh

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>
2022-12-09 14:08:20 -08:00
Josh Spicer
e28358e33b
revert accidental push 2022-12-02 11:53:32 -08:00
Josh Spicer
779fa44930
add 'vim' as a common util to install 2022-12-02 11:52:53 -08:00
Samruddhi Khandale
57e15bc8e8
Update docker-in-docker version (#320)
update dnd
2022-12-02 09:49:20 -08:00
Samruddhi Khandale
7a47fbff00
Node: Fix regression - Installing in ubuntu 18.04 (#319)
Node: Fix regression https://github.com/devcontainers/features/issues/317
2022-12-02 09:48:04 -08:00
Samruddhi Khandale
46dfa11ecd
Github cli - Adds retry logic for find git tags (#310)
* Github cli - Adds retry logic for find git tags

* re-add set -e

* address comment
2022-11-30 13:42:57 -08:00
github-actions[bot]
64f0e10fab
Automated documentation update (#315)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2022-11-29 17:10:37 -08:00
Samruddhi Khandale
cf36e7ac3a
docker-in-docker fix : Use ${devcontainerId} for volume name (#314)
Fix
2022-11-29 17:08:10 -08:00
Chuck Lantz
d1972b4d8d
Use _REMOTE_USER when available (#264)
* Use _REMOTE_USER when available

* Update src/python/install.sh

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>

* Update src/python/install.sh

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>

* Fix java test issue - JDK 18 not available for the "open" distro

* Bump breakfix numbers

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>
Co-authored-by: Josh Spicer <joshspicer@github.com>
2022-11-28 15:07:38 -08:00
Claudio Bandera
4af4c29122
Proposal for fix of #312 (#313)
* Proposal for fix of #312

This change moves the directory separator into the `PIPX_DIR` variable in order to not introduce an error in the case pipx has already been installed systemwide.

* Bump patch version of python feature to 1.0.16
2022-11-28 11:05:21 -08:00
Chuck Lantz
30f2876053
Fix bad path to systemctl (#302) 2022-11-28 10:10:56 -06:00
Samruddhi Khandale
4b3ccf36ea
Adds test coverage (#308)
* Add test coverage

* temp: debug test

* Update tests
2022-11-23 15:03:07 -08:00
github-actions[bot]
188f1ef26b
Automated documentation update (#306)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2022-11-23 12:46:03 -08:00
Paul Yu
133b4cf23c
Optionally install Azure Bicep as part of azure-cli feature (#305)
* Adding azure-cli bicep installer to correctly install on arm64 containers

* Adding a few updates following @joshspicer's review.
2022-11-23 15:18:22 -05:00
Samruddhi Khandale
c4648ab98c
go: fix bug - Go doesn't update version if go is already installed (#303)
* go: fix bug - Go doesn't update version if go is already installed

* Update tests with bash -c
2022-11-23 09:33:50 -08:00
Ilkka Poutanen
173c7ca3c7
Install git before github-cli (#301)
* Install git before github-cli

If building a devcontainer on e.g. `debian:bullseye`, github-cli installation can fail due to git not being installed yet:

```
0 13.38 2022-11-18 13:37:19 (6.08 MB/s) - 'gh_2.20.2_linux_amd64.deb' saved [10
176698/10176698]
#0 13.38
#0 13.40 Selecting previously unselected package gh.
#0 13.41 (Reading database ... 13628 files and directories currently installed.)
#0 13.41 Preparing to unpack .../gh_2.20.2_linux_amd64.deb ...
#0 13.41 Unpacking gh (2.20.2) ...
#0 13.65 dpkg: dependency problems prevent configuration of gh:
#0 13.65  gh depends on git; however:
#0 13.65   Package git is not installed.
#0 13.65
#0 13.65 dpkg: error processing package gh (--install):
#0 13.65  dependency problems - leaving unconfigured
#0 13.66 Errors were encountered while processing:
#0 13.66  gh
#0 13.67 ERROR: Feature "GitHub CLI" (ghcr.io/devcontainers/features/github-cli)
 failed to install! Look at the documentation at https://github.com/devcontainer
s/features/tree/main/src/github-cli for help troubleshooting this error.
```

* bump version

Co-authored-by: Josh Spicer <josh@joshspicer.com>
2022-11-18 10:26:05 -08:00
Samruddhi Khandale
3fc9604dda
Oryx: Build with .NET 6 (#298)
* Oryx: Install dotnet 3.1 runtime

* fix tests

* build with .NET 6 + add tests

* add tests

* fix tests

* shellcheck: nit
2022-11-17 11:55:43 -08:00
etienne-chrp
be4f0498e4
Add Gradle and Maven version parameters to Java (#263)
* Refactor java feature tests grep syntax

The grep with pipe syntax was creating problems with the check helper

Change them in favour of process substitution syntax

* Fix java feature tests about java version

Java 18 is not available anymore in SDKMAN

Some tests asserts were generating false positives

* Add Gradle and Maven version parameters to Java
2022-11-16 16:46:30 -08:00
Samruddhi Khandale
bff3178837
Oryx: Unpin git clone from a single commit (#296) 2022-11-16 10:49:06 -08:00
Samruddhi Khandale
1e35500bda
Node: Fix bug - version set by Feature is not default (#294)
* Node:Fix bug version set by Feature is not default

* node not supported for ubuntu:bionic
2022-11-15 14:51:00 -08:00
Samruddhi Khandale
f9acb6aae1
Python bug fix - Add jupyterlab even if python is not installed by Feature but exists (#244)
* python fix bug

* fix test

* address comments

* address comment
2022-11-15 13:26:26 -08:00
github-actions[bot]
a5655189a2
Automated documentation update (#292)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2022-11-15 08:23:00 -08:00
Mikey Lombardi (He/Him)
474444fa9f
(GH-198) Add extended option to hugo feature (#240)
Prior to this change, the hugo feature only supported specifying the
version of Hugo to install. Hugo is available in two builds: standard,
which the feature already installs, and extended, which includes
functionality for post-processing CSS/SCSS/SASS and JavaScript.

This change adds a new `extended` option to the hugo feature, allowing
users to specify that they require the extended build of Hugo. It
defaults to `false` and installs the standard build of Hugo.

- Resolves #198
2022-11-15 08:19:33 -08:00
github-actions[bot]
ada30c21f5
Automated documentation update for Azure CLI and CUDA (#289)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2022-11-14 13:47:51 -08:00
JP Ungaretti
58fed08dcf
Add support for CUDA 11.8 in nvidia-cuda (#267)
* Add latest CUDA versions

* Move cuDNN version check

* Check CUDA version
2022-11-14 13:42:17 -08:00
Paul Yu
eafa28287e
Add new option to install azure-cli extensions (#165)
* Add new option for azure-cli extensions

* Update to install az extensions as $_REMOTE_USER

* Skip unknown extensions

* Change azure cli extension option type to string

* Adding test for azure-cli extensions
2022-11-14 12:22:02 -08:00
JP Ungaretti
e00724a0c6
Add git extension for JupyterLab to Python feature (#286)
* Add git extension

* Bump version
2022-11-14 11:46:13 -08:00
Chuck Lantz
17580ee22f
Add .NET 7, drop .NET 5 (#269)
* Add .NET 7, drop .NET 5

* Add libssl3 to common-utils for jammy

* Handle lts/latest hard coding

* Fix, improve tests

* Bump version

* Fix situation where version could come from either MS repo or OS

* Remove unused option

* Bump common version

* Remove unused function

* Restore DOTNET_ROOT per feedback
2022-11-14 11:41:32 -08:00
github-actions[bot]
258b107b39
Automated documentation update (#287)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2022-11-14 11:40:25 -08:00
github-actions[bot]
0e25800486
Automated documentation update (#282)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2022-11-12 11:24:57 -08:00
Chuck Lantz
e9c4f9f8c5
Fix property name 2022-11-12 11:22:41 -08:00
github-actions[bot]
7172641514
Automated documentation update (#281)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2022-11-12 11:14:58 -08:00
github-actions[bot]
00a51775eb
Automated documentation update (#279)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2022-11-12 11:14:29 -08:00
Chuck Lantz
1c61d1a039
Add test, bump version for extraNixConfig (#280) 2022-11-12 11:12:21 -08:00
Nick Hu
a2b1c19a51
Nix feature: allow extra configuration of /etc/nix/nix.conf (#277) 2022-11-12 10:33:16 -08:00
Chuck Lantz
f7f05f76fa
Fix regression with Azure CLI, privs (#272) 2022-11-10 17:03:21 -08:00
Chuck Lantz
3020d6da64
Fix python feature issue #258, improve tests, fix oryx bug (#261)
* Fix #258, improve tests, fix oryx bug
* Drop Debian 9 from tests given it is out of support
2022-11-07 12:46:23 -06:00
github-actions[bot]
73a9c7d382
Automated documentation update (#257)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2022-11-02 17:02:26 -07:00
Chuck Lantz
d003c1b1ac
Add missing notes 2022-11-02 18:39:11 -05:00
github-actions[bot]
b7c70d3d9b
Automated documentation update (#254)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2022-11-01 14:18:13 -07:00
Samruddhi Khandale
752ba5db21
Test actions - Add more base images (#245)
update base images
2022-11-01 14:06:27 -07:00
Samruddhi Khandale
a94558576c
Oryx - git clone: Pin to an older commit (#253)
pin: git clone
2022-11-01 11:28:41 -07:00
github-actions[bot]
268368beeb
Automated documentation update (#252)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2022-11-01 10:04:58 -07:00
Chuck Lantz
0752a52b0c
Nix feature (#228) 2022-11-01 12:02:02 -05:00
Samruddhi Khandale
748be9320c
kubectl-helm-minikube - Remove 'ms-kubernetes-tools.vscode-kubernetes-tools' extension (#251)
update kubectl-helm-minikube
2022-11-01 09:17:03 -07:00
github-actions[bot]
1313517fc4
Automated documentation update (#250)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2022-10-31 15:10:22 -07:00
Brigit Murtaugh
2ce89c4a57
Update README.md (#243)
* Update README.md

* Update to website
2022-10-31 07:55:26 -07:00
Samruddhi Khandale
9366ef7ed1
Node: Fix failure when version:none (#247)
fix version:none
2022-10-28 16:50:48 -07:00
github-actions[bot]
f1c981d064
Automated documentation update (#246)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2022-10-28 13:59:09 -07:00
Alessandro (Ale) Segala
0ee38a48e4
Install golangci-lint from prebuilt binaries and allow specifying its version (#238)
* Install golangci-lint from prebuilt binaries and allow specifying its version

* Updated as requested

* Update src/go/devcontainer-feature.json

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>

* Updated install path

Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>
2022-10-28 13:57:57 -07:00
Aurelio Jargas
85d2150997
github-cli: Remove duplicated find_version_from_git_tags () (#235)
This function was defined twice in the install script for GitHub CLI, in
old lines 76 and 161. This commit removes the first definition.

The only function calls were on old lines 201 and 222. Since they appear
after the second function definition at line 161, the first one at line
76 never got called, so it's safe to remove it.

I confirmed that this was the only file in this repository where this
function was duplicated:  

    $ git grep '^ *find_version_from_git_tags *('
    src/docker-from-docker/install.sh:find_version_from_git_tags() {
    src/docker-in-docker/install.sh:find_version_from_git_tags() {
    src/git-lfs/install.sh:find_version_from_git_tags() {
    src/github-cli/install.sh:find_version_from_git_tags() {
    src/github-cli/install.sh:find_version_from_git_tags() {
    src/go/install.sh:find_version_from_git_tags() {
    src/kubectl-helm-minikube/install.sh:find_version_from_git_tags() {
    src/php/install.sh:find_version_from_git_tags() {
    src/powershell/install.sh:find_version_from_git_tags() {
    src/python/install.sh:find_version_from_git_tags() {
    src/ruby/install.sh:find_version_from_git_tags() {
    src/rust/install.sh:find_version_from_git_tags() {
    src/terraform/install.sh:find_version_from_git_tags() {
    $
2022-10-28 10:46:16 -07:00
github-actions[bot]
22050f2fd4
Automated documentation update (#242)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2022-10-28 10:44:39 -07:00
Chuck Lantz
2963ae9119
Fix privs in Node, regressions from #199 (#241)
Co-authored-by: Samruddhi Khandale <skhandale@microsoft.com>
2022-10-28 12:32:58 -05:00
Samruddhi Khandale
ab021f0dfb
Fix oryx bug - Add PIP_CACHE_DIR (#239)
* oryx update

* bump version

* update comment
2022-10-26 15:20:47 -07:00
Edmundo Gonzalez
520a4abc40
Python version 3.11 (#237)
* Adding 3.11 option

* Updating tests.
2022-10-25 16:07:05 -07:00
github-actions[bot]
fd31e97db0
Automated documentation update (#233)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2022-10-21 07:40:36 -07:00
Kevin Klopfenstein
7ae8c5c16d
Add default-address-pool setting (#223) 2022-10-21 07:31:04 -07:00
github-actions[bot]
4dae930c16
Automated documentation update (#231)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2022-10-19 09:20:09 -07:00
Daniel Braun
40206f4774
Update devcontainer-feature.json (#230)
* Update devcontainer-feature.json

Minor typo fix

* Update devcontainer-feature.json

Co-authored-by: Josh Spicer <josh@joshspicer.com>
2022-10-19 08:56:52 -07:00
github-actions[bot]
aad4e3a7af
Automated documentation update (#213)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2022-10-18 16:40:10 -07:00
Josh Spicer
67b15cae12
add installsAfter: common-utils to all Features (#214) 2022-10-18 16:30:56 -07:00
github-actions[bot]
7860eb85a4
Automated documentation update (#229)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2022-10-18 16:30:21 -07:00
Josh Spicer
2bec6f056c
clean up AWS feature description (#225)
* clean up AWS feature description

* Update devcontainer-feature.json
2022-10-18 16:26:28 -07:00
Josh Spicer
43f0b34aa3
bump docker-in-docker to 1.0.7 2022-10-17 08:27:44 -07:00
Charlie Andrews
2c82571f42
Quote var in comparison in docker-in-docker install script (#224) 2022-10-17 08:26:58 -07:00
github-actions[bot]
530997ce54
Automated documentation update (#218)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2022-10-13 08:47:25 -07:00
Chuck Lantz
a244dc394f
Fix formatting for desktop-lite note (#216) 2022-10-12 17:31:29 -07:00
eitsupi
a8cb375d46
Ensure remove apt-update cache at the beginning and end of the scripts (#210)
* remove apt lists

* bump versions
2022-10-10 15:33:01 -07:00
github-actions[bot]
065b5ec9e1
Automated documentation update (#205)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2022-10-06 15:57:17 -07:00
github-actions[bot]
14c7ee7897
Automated documentation update (#202)
Automated documentation update [skip ci]

Co-authored-by: github-actions <github-actions@github.com>
2022-10-06 15:45:36 -05:00
Samruddhi Khandale
2d63a582d9
Common-utils: Fix bug - optional first run image specific notice (#201)
* add DEV_CONTAINERS_DIR as containerEnv

* fix path

* update test

* remove containerEnv
2022-10-06 15:44:43 -05:00
Josh Spicer
602c3ec7b6
Move conda description to description property (#196)
move conda description to description property
2022-10-06 14:10:40 -05:00
319 changed files with 10024 additions and 2348 deletions

View file

@ -1,15 +0,0 @@
{
"image": "mcr.microsoft.com/vscode/devcontainers/javascript-node:0-18",
"remoteUser": "node",
"customizations": {
"vscode": {
"extensions": [
"mads-hartmann.bash-ide-vscode"
]
}
},
"features": {
"ghcr.io/devcontainers/features/docker-in-docker:1": {}
},
"postCreateCommand": "npm install -g @devcontainers/cli"
}

View file

@ -0,0 +1,17 @@
{
"image": "mcr.microsoft.com/devcontainers/javascript-node:1-18",
"features": {
"ghcr.io/devcontainers/features/docker-in-docker:2": {}
},
"postCreateCommand": "npm install -g @devcontainers/cli",
"hostRequirements": {
"cpus": 4
},
"customizations": {
"vscode": {
"extensions": [
"mads-hartmann.bash-ide-vscode"
]
}
}
}

View file

@ -0,0 +1,37 @@
name: "Stress test - Docker in Docker"
on:
pull_request:
paths:
- 'src/docker-in-docker/**'
workflow_dispatch:
jobs:
test:
strategy:
matrix:
test-pass: [ 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50 ]
fail-fast: false
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: "Install latest devcontainer CLI"
run: npm install -g @devcontainers/cli
- name: "Generating tests for 'docker-in-docker' which validates if docker daemon is running"
run: devcontainer features test --skip-scenarios -f docker-in-docker -i mcr.microsoft.com/devcontainers/base:ubuntu .
test-onCreate:
strategy:
matrix:
test-pass: [ 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50 ]
fail-fast: false
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: "Install latest devcontainer CLI"
run: npm install -g @devcontainers/cli
- name: "Generating tests for 'docker-in-docker' which validates if docker daemon is available within 'onCreateCommand'"
run: devcontainer features test -f docker-in-docker --skip-autogenerated --filter "docker_with_on_create_command"

View file

@ -9,7 +9,7 @@ jobs:
shellchecker: shellchecker:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: Shell Linter - name: Shell Linter
uses: azohra/shell-linter@v0.6.0 uses: azohra/shell-linter@v0.6.0

View file

@ -15,7 +15,7 @@ jobs:
shellchecker: shellchecker:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: Shell Linter - name: Shell Linter
uses: azohra/shell-linter@v0.6.0 uses: azohra/shell-linter@v0.6.0

View file

@ -10,7 +10,7 @@ jobs:
if: ${{ github.ref == 'refs/heads/main' }} if: ${{ github.ref == 'refs/heads/main' }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: "Publish" - name: "Publish"
uses: devcontainers/action@v1 uses: devcontainers/action@v1

View file

@ -18,7 +18,7 @@ jobs:
"common-utils", "common-utils",
"conda", "conda",
"desktop-lite", "desktop-lite",
"docker-from-docker", "docker-outside-of-docker",
"docker-in-docker", "docker-in-docker",
"dotnet", "dotnet",
"git", "git",
@ -38,17 +38,19 @@ jobs:
"rust", "rust",
"sshd", "sshd",
"terraform", "terraform",
"nix",
] ]
baseImage: baseImage:
[ [
"ubuntu:focal", "ubuntu:focal",
"ubuntu:jammy", "ubuntu:jammy",
"debian:11", "debian:11",
"debian:12",
"mcr.microsoft.com/devcontainers/base:ubuntu", "mcr.microsoft.com/devcontainers/base:ubuntu",
"mcr.microsoft.com/devcontainers/base:debian", "mcr.microsoft.com/devcontainers/base:debian",
] ]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: "Install latest devcontainer CLI" - name: "Install latest devcontainer CLI"
run: npm install -g @devcontainers/cli run: npm install -g @devcontainers/cli
@ -68,7 +70,7 @@ jobs:
"common-utils", "common-utils",
"conda", "conda",
"desktop-lite", "desktop-lite",
"docker-from-docker", "docker-outside-of-docker",
"docker-in-docker", "docker-in-docker",
"dotnet", "dotnet",
"git", "git",
@ -88,9 +90,10 @@ jobs:
"rust", "rust",
"sshd", "sshd",
"terraform", "terraform",
"nix",
] ]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: "Install latest devcontainer CLI" - name: "Install latest devcontainer CLI"
run: npm install -g @devcontainers/cli run: npm install -g @devcontainers/cli
@ -102,10 +105,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
continue-on-error: true continue-on-error: true
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: "Install latest devcontainer CLI" - name: "Install latest devcontainer CLI"
run: npm install -g @devcontainers/cli run: npm install -g @devcontainers/cli
- name: "Testing global scenarios" - name: "Testing global scenarios"
run: devcontainer features test --global-scenarios-only . run: devcontainer features test --global-scenarios-only .

View file

@ -19,7 +19,7 @@ jobs:
test: test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: "Install latest devcontainer CLI" - name: "Install latest devcontainer CLI"
run: npm install -g @devcontainers/cli run: npm install -g @devcontainers/cli

View file

@ -18,7 +18,7 @@ jobs:
common-utils: ./**/common-utils/** common-utils: ./**/common-utils/**
conda: ./**/conda/** conda: ./**/conda/**
desktop-lite: ./**/desktop-lite/** desktop-lite: ./**/desktop-lite/**
docker-from-docker: ./**/docker-from-docker/** docker-outside-of-docker: ./**/docker-outside-of-docker/**
docker-in-docker: ./**/docker-in-docker/** docker-in-docker: ./**/docker-in-docker/**
dotnet: ./**/dotnet/** dotnet: ./**/dotnet/**
git: ./**/git/** git: ./**/git/**
@ -38,6 +38,7 @@ jobs:
rust: ./**/rust/** rust: ./**/rust/**
sshd: ./**/sshd/** sshd: ./**/sshd/**
terraform: ./**/terraform/** terraform: ./**/terraform/**
nix: ./**/nix/**
test: test:
needs: [detect-changes] needs: [detect-changes]
@ -51,11 +52,12 @@ jobs:
"ubuntu:focal", "ubuntu:focal",
"ubuntu:jammy", "ubuntu:jammy",
"debian:11", "debian:11",
"debian:12",
"mcr.microsoft.com/devcontainers/base:ubuntu", "mcr.microsoft.com/devcontainers/base:ubuntu",
"mcr.microsoft.com/devcontainers/base:debian", "mcr.microsoft.com/devcontainers/base:debian",
] ]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: "Install latest devcontainer CLI" - name: "Install latest devcontainer CLI"
run: npm install -g @devcontainers/cli run: npm install -g @devcontainers/cli
@ -71,10 +73,10 @@ jobs:
matrix: matrix:
features: ${{ fromJSON(needs.detect-changes.outputs.features) }} features: ${{ fromJSON(needs.detect-changes.outputs.features) }}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: "Install latest devcontainer CLI" - name: "Install latest devcontainer CLI"
run: npm install -g @devcontainers/cli run: npm install -g @devcontainers/cli
- name: "Testing '${{ matrix.features }}' scenarios" - name: "Testing '${{ matrix.features }}' scenarios"
run: devcontainer features test -f ${{ matrix.features }} --skip-autogenerated . run: devcontainer features test -f ${{ matrix.features }} --skip-autogenerated .

View file

@ -8,9 +8,10 @@ on:
jobs: jobs:
generate: generate:
runs-on: ubuntu-latest runs-on: ubuntu-latest
environment: documentation
if: "github.ref == 'refs/heads/main'" if: "github.ref == 'refs/heads/main'"
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: Generate Documentation - name: Generate Documentation
uses: devcontainers/action@v1 uses: devcontainers/action@v1
@ -18,10 +19,10 @@ jobs:
generate-docs: "true" generate-docs: "true"
base-path-to-features: "./src" base-path-to-features: "./src"
- name: Add and Commit Documentation - name: Create a PR for Documentation
id: push_image_info id: push_image_info
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.PAT }}
run: | run: |
set -e set -e
echo "Start." echo "Start."
@ -42,5 +43,12 @@ jobs:
# Push # Push
if [ "$NO_UPDATES" != "true" ] ; then if [ "$NO_UPDATES" != "true" ] ; then
git push origin "$branch" git push origin "$branch"
gh pr create --title "$message" --body "$message" gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
/repos/${GITHUB_REPOSITORY}/pulls \
-f title="$message" \
-f body="$message" \
-f head="$branch" \
-f base='main'
fi fi

View file

@ -0,0 +1,52 @@
name: "Updates vendor 'dotnet-install' script"
on:
workflow_dispatch:
schedule:
- cron: '0 0 * * 0' # Runs every Sunday at midnight UTC (adjust as needed)
jobs:
fetch-latest-dotnet-install:
runs-on: ubuntu-latest
environment: documentation # grants access to secrets.PAT, for creating pull requests
steps:
- uses: actions/checkout@v3
- name: Run fetch-latest-dotnet-install.sh
run: src/dotnet/scripts/fetch-latest-dotnet-install.sh
- name: Create a PR for dotnet-install.sh
id: push_image_info
env:
GITHUB_TOKEN: ${{ secrets.PAT }}
run: |
set -e
echo "Start."
# Configure git and Push updates
git config --global user.email github-actions@github.com
git config --global user.name github-actions
git config pull.rebase false
branch=automated-script-update-$GITHUB_RUN_ID
git checkout -b $branch
message='[Updates] Automated vendor 'dotnet-install' script'
# Add / update and commit
git add src/dotnet/scripts/vendor/dotnet-install.sh
git commit -m 'Automated dotnet-install script update' || export NO_UPDATES=true
# Bump version and push
if [ "$NO_UPDATES" != "true" ] ; then
echo "$(jq --indent 4 '.version = (.version | split(".") | map(tonumber) | .[2] += 1 | join("."))' src/dotnet/devcontainer-feature.json)" > src/dotnet/devcontainer-feature.json
git add src/dotnet/devcontainer-feature.json
git commit -m 'Bump version'
git push origin "$branch"
gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
/repos/${GITHUB_REPOSITORY}/pulls \
-f title="$message" \
-f body="$message" \
-f head="$branch" \
-f base="$GITHUB_REF_NAME"
fi

View file

@ -0,0 +1,16 @@
name: "Validate devcontainer-feature.json files"
on:
workflow_dispatch:
pull_request:
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: "Validate devcontainer-feature.json files"
uses: devcontainers/action@v1
with:
validate-only: "true"
base-path-to-features: "./src"

60
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,60 @@
**Thanks for taking the time to contribute! ❤️**
All types of contributions are encouraged and valued, no matter if it's a bug
report 🐛, a feature request 💡, or a Pull Request 🚀.
- **❓ I have a question:** Ask in [our dev container community Slack channel]
- **🐛 I found a bug:** [Open an Issue]
- **💡 I have an idea:** [Open an Issue]
- **💻 I want to code:** See below
If you like the project, but just don't have time to contribute, that's OK too!
You can also star the project ⭐, rave about it online 💬, or add a link to us
🔗 in your project's readme.
⚠️ You must never report security 🔒 related issues, vulnerabilities or bugs
including sensitive information to the issue tracker, or elsewhere in public.
Instead, please [report them to the Microsoft Security Response Center]. You can
read more about our security policy in [`SECURITY.md`].
## Contributing code
👨‍💼 This repository is a collection of dev container Features managed by dev
container spec maintainers. This repository will **only accept improvements and
bug fixes** for the [current set of maintained Features].
🚀 If you're looking to create a new Feature, then we encourage adding it to a
separate repository of your control. The [devcontainers/feature-starter]
repository has more guidance on self authoring Features.
💡 Once you've self authored the Features and if you'd like to share them with
the community, then we'd recommend [adding it to the index].
👷‍ If you've identified an issue and you want to fix it, here's how you can get
started:
1. 🔀 Fork the repo
2. 💻 Open the repo in your editor
3. 👨‍💻 Add your changes to your workspace
4. ✨ [Test your changes using `devcontainer features test`] to make sure
everything still works
5. 🆚 Bump the version of the feature you changed according to [semver]
6. 🔖 Commit & push your changes
7. 🔁 Open a PR to get your changes merged
8. 🚀 Profit!
👩‍⚖️ When contributing code to this project, you may be asked to agree to our
[Contributor License Agreement].
<!-- prettier-ignore-start -->
[our dev container community Slack channel]: https://aka.ms/devcontainer_community
[open an issue]: https://github.com/devcontainers/features/issues/new
[current set of maintained Features]: https://github.com/devcontainers/features/tree/main/src
[devcontainers/feature-starter]: https://github.com/devcontainers/feature-starter#readme
[adding it to the index]: https://github.com/devcontainers/feature-starter#adding-features-to-the-index
[report them to the Microsoft Security Response Center]: https://msrc.microsoft.com/create-report
[`SECURITY.md`]: https://github.com/devcontainers/spec/blob/main/SECURITY.md
[contributor license agreement]: https://opensource.microsoft.com/cla/
[Test your changes using `devcontainer features test`]: https://github.com/devcontainers/cli/blob/main/docs/features/test.md
[semver]: https://semver.org/
<!-- prettier-ignore-end -->

View file

@ -4,36 +4,28 @@
<td style="width: 140px; text-align: center;"><a href="https://github.com/devcontainers"><img width="128px" src="https://raw.githubusercontent.com/microsoft/fluentui-system-icons/78c9587b995299d5bfc007a0077773556ecb0994/assets/Cube/SVG/ic_fluent_cube_32_filled.svg" alt="devcontainers organization logo"/></a></td> <td style="width: 140px; text-align: center;"><a href="https://github.com/devcontainers"><img width="128px" src="https://raw.githubusercontent.com/microsoft/fluentui-system-icons/78c9587b995299d5bfc007a0077773556ecb0994/assets/Cube/SVG/ic_fluent_cube_32_filled.svg" alt="devcontainers organization logo"/></a></td>
<td> <td>
<strong>Development Container 'Features'</strong><br /> <strong>Development Container 'Features'</strong><br />
<i>A set of simple and reusable 'features'. Quickly add a language/tool/CLI to a development container. <i>A set of simple and reusable Features. Quickly add a language/tool/CLI to a development container.
</td> </td>
</tr></table> </tr></table>
'Features' are self-contained units of installation code and development container configuration. Features are designed 'Features' are self-contained units of installation code and development container configuration. Features are designed
to install atop a wide-range of base container images (**this repo focuses on `debian` based images**). to install atop a wide-range of base container images.
Missing a CLI or language in your otherwise _perfect_ container image? Add the relevant 'feature' to the `features` Missing a CLI or language in your otherwise _perfect_ container image? Add the relevant Feature to the `features`
property of a [`devcontainer.json`](https://containers.dev/implementors/json_reference/#general-properties). A property of a [`devcontainer.json`](https://containers.dev/implementors/json_reference/#general-properties). A
[tool supporting the dev container specification](https://containers.dev/supporting) is required to build a development [tool supporting the dev container specification](https://containers.dev/supporting) is required to build a development
container. container.
⚠️ Development container 'features' are a You may learn about Features at [containers.dev](https://containers.dev/implementors/features/), which is the website for the dev container specification.
[**proposed**](https://github.com/devcontainers/spec/blob/main/proposals/devcontainer-features.md) addition to the
[development container specification](https://containers.dev/implementors/spec/). **Please note that 'features' are in
preview and subject to breaking changes**.
Once the [**proposed**](https://github.com/devcontainers/spec/blob/main/proposals/devcontainer-features.md)
specification is accepted, implementation details will be published at
[https://containers.dev](https://containers.dev/).
## Usage ## Usage
To reference a feature from this repository, add the desired features to a `devcontainer.json`. Each feature has a `README.md` that shows how to reference the feature and which options are available for that feature. To reference a Feature from this repository, add the desired Features to a `devcontainer.json`. Each Feature has a `README.md` that shows how to reference the Feature and which options are available for that Feature.
The example below installs the `go` and `docker-in-docker` declared in the [`./src`](./src) directory of this The example below installs the `go` and `docker-in-docker` declared in the [`./src`](./src) directory of this
repository. repository.
See the relevant feature's README for supported options. See the relevant Feature's README for supported options.
```jsonc ```jsonc
"name": "my-project-devcontainer", "name": "my-project-devcontainer",
@ -51,7 +43,7 @@ See the relevant feature's README for supported options.
The `:latest` version annotation is added implicitly if omitted. To pin to a specific package version The `:latest` version annotation is added implicitly if omitted. To pin to a specific package version
([example](https://github.com/devcontainers/features/pkgs/container/features/go/versions)), append it to the end of the ([example](https://github.com/devcontainers/features/pkgs/container/features/go/versions)), append it to the end of the
feature. Features follow semantic versioning conventions, so you can pin to a major version `:1`, minor version `:1.0`, or patch version `:1.0.0` by specifying the appropriate label. Feature. Features follow semantic versioning conventions, so you can pin to a major version `:1`, minor version `:1.0`, or patch version `:1.0.0` by specifying the appropriate label.
```jsonc ```jsonc
"features": { "features": {
@ -63,7 +55,7 @@ feature. Features follow semantic versioning conventions, so you can pin to a ma
The [devcontainer CLI reference implementation](https://github.com/devcontainers/cli) (or a The [devcontainer CLI reference implementation](https://github.com/devcontainers/cli) (or a
[supporting tool](https://containers.dev/supporting)) can be used to build a project's dev container declaring [supporting tool](https://containers.dev/supporting)) can be used to build a project's dev container declaring
'features'. Features.
```bash ```bash
git clone <my-project-with-devcontainer> git clone <my-project-with-devcontainer>
@ -97,7 +89,7 @@ devcontainer build --workspace-folder <path-to-my-project-with-devcontainer>
... ...
``` ```
- [`src`](src) - A collection of subfolders, each declaring a feature. Each subfolder contains at least a - [`src`](src) - A collection of subfolders, each declaring a Feature. Each subfolder contains at least a
`devcontainer-feature.json` and an `install.sh` script. `devcontainer-feature.json` and an `install.sh` script.
- [`test`](test) - Mirroring `src`, a folder-per-feature with at least a `test.sh` script. The - [`test`](test) - Mirroring `src`, a folder-per-feature with at least a `test.sh` script. The
[`devcontainer` CLI](https://github.com/devcontainers/cli) will execute [`devcontainer` CLI](https://github.com/devcontainers/cli) will execute
@ -105,15 +97,19 @@ devcontainer build --workspace-folder <path-to-my-project-with-devcontainer>
## Contributions ## Contributions
### Creating your own collection of features ### Creating your own collection of Features
The [feature distribution specification](https://github.com/devcontainers/spec/blob/main/proposals/devcontainer-features-distribution.md) outlines a pattern for community members and organizations to self-author features in repositories they control. The [Feature distribution specification](https://containers.dev/implementors/features-distribution/) outlines a pattern for community members and organizations to self-author Features in repositories they control.
A template repo [`devcontainers/feature-template`](https://github.com/devcontainers/feature-template) and [GitHub Action](https://github.com/devcontainers/action) are available to help bootstrap self-authored features. A template repo [`devcontainers/feature-template`](https://github.com/devcontainers/feature-template) and [GitHub Action](https://github.com/devcontainers/action) are available to help bootstrap self-authored Features.
We are eager to hear your feedback on self-authoring! Please provide comments and feedback on [spec issue #70](https://github.com/devcontainers/spec/issues/70). We are eager to hear your feedback on self-authoring! Please provide comments and feedback on [spec issue #70](https://github.com/devcontainers/spec/issues/70).
### Contributing to this repository ### Contributing to this repository
This repository will accept improvement and bug fix contributions related to the This repository will accept improvement and bug fix contributions related to the
[current set of maintained features](./src). [current set of maintained Features](./src).
🤝 You can read more about how to contribute in [`CONTRIBUTING.md`]. ❤️
[`CONTRIBUTING.md`]: CONTRIBUTING.md

View file

@ -11,3 +11,10 @@ As covered in the [user FAQ](https://docs.anaconda.com/anaconda/user-guide/faq)
```bash ```bash
conda install python=3.7 conda install python=3.7
``` ```
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.

View file

@ -7,9 +7,7 @@
```json ```json
"features": { "features": {
"ghcr.io/devcontainers/features/anaconda:1": { "ghcr.io/devcontainers/features/anaconda:1": {}
"version": "latest"
}
} }
``` ```
@ -34,6 +32,13 @@ conda install python=3.7
``` ```
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.
--- ---
_Note: This file was auto-generated from the [devcontainer-feature.json](https://github.com/devcontainers/features/blob/main/src/anaconda/devcontainer-feature.json). Add additional notes to a `NOTES.md`._ _Note: This file was auto-generated from the [devcontainer-feature.json](https://github.com/devcontainers/features/blob/main/src/anaconda/devcontainer-feature.json). Add additional notes to a `NOTES.md`._

View file

@ -1,6 +1,6 @@
{ {
"id": "anaconda", "id": "anaconda",
"version": "1.0.7", "version": "1.0.11",
"name": "Anaconda", "name": "Anaconda",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/anaconda", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/anaconda",
"options": { "options": {
@ -16,5 +16,8 @@
"containerEnv": { "containerEnv": {
"CONDA_DIR": "/usr/local/conda", "CONDA_DIR": "/usr/local/conda",
"PATH": "/usr/local/conda/bin:${PATH}" "PATH": "/usr/local/conda/bin:${PATH}"
} },
"installsAfter": [
"ghcr.io/devcontainers/features/common-utils"
]
} }

View file

@ -8,14 +8,17 @@
# Maintainer: The VS Code and Codespaces Teams # Maintainer: The VS Code and Codespaces Teams
VERSION=${VERSION:-"latest"} VERSION="${VERSION:-"latest"}"
USERNAME=${USERNAME:-"automatic"} USERNAME="${USERNAME:-"${_REMOTE_USER:-"automatic"}"}"
UPDATE_RC=${UPDATE_RC:-"true"} UPDATE_RC="${UPDATE_RC:-"true"}"
CONDA_DIR=${CONDA_DIR:-"/usr/local/conda"} CONDA_DIR="${CONDA_DIR:-"/usr/local/conda"}"
set -eux set -eux
export DEBIAN_FRONTEND=noninteractive export DEBIAN_FRONTEND=noninteractive
# Clean up
rm -rf /var/lib/apt/lists/*
if [ "$(id -u)" -ne 0 ]; then if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1 exit 1
@ -64,7 +67,10 @@ updaterc() {
# Checks if packages are installed and installs them if not # Checks if packages are installed and installs them if not
check_packages() { check_packages() {
if ! dpkg -s "$@" > /dev/null 2>&1; then if ! dpkg -s "$@" > /dev/null 2>&1; then
apt-get update -y if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then
echo "Running apt-get update..."
apt-get update -y
fi
apt-get -y install --no-install-recommends "$@" apt-get -y install --no-install-recommends "$@"
fi fi
} }
@ -128,4 +134,7 @@ if [ -f "/etc/bash.bashrc" ]; then
echo "${notice_script}" | tee -a /etc/bash.bashrc echo "${notice_script}" | tee -a /etc/bash.bashrc
fi fi
echo "Done!" # Clean up
rm -rf /var/lib/apt/lists/*
echo "Done!"

7
src/aws-cli/NOTES.md Normal file
View file

@ -0,0 +1,7 @@
Available versions of the AWS CLI can be found here: https://github.com/aws/aws-cli/blob/v2/CHANGELOG.rst.
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.

View file

@ -7,9 +7,7 @@ Installs the AWS CLI along with needed dependencies. Useful for base Dockerfiles
```json ```json
"features": { "features": {
"ghcr.io/devcontainers/features/aws-cli:1": { "ghcr.io/devcontainers/features/aws-cli:1": {}
"version": "latest"
}
} }
``` ```
@ -17,8 +15,21 @@ Installs the AWS CLI along with needed dependencies. Useful for base Dockerfiles
| Options Id | Description | Type | Default Value | | Options Id | Description | Type | Default Value |
|-----|-----|-----|-----| |-----|-----|-----|-----|
| version | Select or enter an AWS CLI version. (Available versions here: https://github.com/aws/aws-cli/blob/v2/CHANGELOG.rst) | string | latest | | version | Select or enter an AWS CLI version. | string | latest |
## Customizations
### VS Code Extensions
- `AmazonWebServices.aws-toolkit-vscode`
Available versions of the AWS CLI can be found here: https://github.com/aws/aws-cli/blob/v2/CHANGELOG.rst.
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.
--- ---

View file

@ -1,6 +1,6 @@
{ {
"id": "aws-cli", "id": "aws-cli",
"version": "1.0.3", "version": "1.0.7",
"name": "AWS CLI", "name": "AWS CLI",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/aws-cli", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/aws-cli",
"description": "Installs the AWS CLI along with needed dependencies. Useful for base Dockerfiles that often are missing required install dependencies like gpg.", "description": "Installs the AWS CLI along with needed dependencies. Useful for base Dockerfiles that often are missing required install dependencies like gpg.",
@ -11,7 +11,7 @@
"latest" "latest"
], ],
"default": "latest", "default": "latest",
"description": "Select or enter an AWS CLI version. (Available versions here: https://github.com/aws/aws-cli/blob/v2/CHANGELOG.rst)" "description": "Select or enter an AWS CLI version."
} }
}, },
"customizations": { "customizations": {
@ -20,5 +20,8 @@
"AmazonWebServices.aws-toolkit-vscode" "AmazonWebServices.aws-toolkit-vscode"
] ]
} }
} },
"installsAfter": [
"ghcr.io/devcontainers/features/common-utils"
]
} }

View file

@ -9,6 +9,9 @@
set -e set -e
# Clean up
rm -rf /var/lib/apt/lists/*
VERSION=${VERSION:-"latest"} VERSION=${VERSION:-"latest"}
AWSCLI_GPG_KEY=FB5DB77FD5C118B80511ADA8A6310ACC4672475C AWSCLI_GPG_KEY=FB5DB77FD5C118B80511ADA8A6310ACC4672475C
@ -47,21 +50,6 @@ if [ "$(id -u)" -ne 0 ]; then
exit 1 exit 1
fi fi
# Get central common setting
get_common_setting() {
if [ "${common_settings_file_loaded}" != "true" ]; then
curl -sfL "https://aka.ms/vscode-dev-containers/script-library/settings.env" 2>/dev/null -o /tmp/vsdc-settings.env || echo "Could not download settings file. Skipping."
common_settings_file_loaded=true
fi
if [ -f "/tmp/vsdc-settings.env" ]; then
local multi_line=""
if [ "$2" = "true" ]; then multi_line="-z"; fi
local result="$(grep ${multi_line} -oP "$1=\"?\K[^\"]+" /tmp/vsdc-settings.env | tr -d '\0')"
if [ ! -z "${result}" ]; then declare -g $1="${result}"; fi
fi
echo "$1=${!1}"
}
apt_get_update() apt_get_update()
{ {
echo "Running apt-get update..." echo "Running apt-get update..."
@ -71,7 +59,10 @@ apt_get_update()
# Checks if packages are installed and installs them if not # Checks if packages are installed and installs them if not
check_packages() { check_packages() {
if ! dpkg -s "$@" > /dev/null 2>&1; then if ! dpkg -s "$@" > /dev/null 2>&1; then
apt_get_update if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then
echo "Running apt-get update..."
apt-get update -y
fi
apt-get -y install --no-install-recommends "$@" apt-get -y install --no-install-recommends "$@"
fi fi
} }
@ -83,9 +74,6 @@ check_packages curl ca-certificates gnupg2 dirmngr unzip
verify_aws_cli_gpg_signature() { verify_aws_cli_gpg_signature() {
local filePath=$1 local filePath=$1
local sigFilePath=$2 local sigFilePath=$2
get_common_setting AWSCLI_GPG_KEY
get_common_setting AWSCLI_GPG_KEY_MATERIAL true
local awsGpgKeyring=aws-cli-public-key.gpg local awsGpgKeyring=aws-cli-public-key.gpg
echo "${AWSCLI_GPG_KEY_MATERIAL}" | gpg --dearmor > "./${awsGpgKeyring}" echo "${AWSCLI_GPG_KEY_MATERIAL}" | gpg --dearmor > "./${awsGpgKeyring}"
@ -133,4 +121,7 @@ echo "(*) Installing AWS CLI..."
install install
# Clean up
rm -rf /var/lib/apt/lists/*
echo "Done!" echo "Done!"

7
src/azure-cli/NOTES.md Normal file
View file

@ -0,0 +1,7 @@
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.

View file

@ -7,9 +7,7 @@ Installs the Azure CLI along with needed dependencies. Useful for base Dockerfil
```json ```json
"features": { "features": {
"ghcr.io/devcontainers/features/azure-cli:1": { "ghcr.io/devcontainers/features/azure-cli:1": {}
"version": "latest"
}
} }
``` ```
@ -18,7 +16,23 @@ Installs the Azure CLI along with needed dependencies. Useful for base Dockerfil
| Options Id | Description | Type | Default Value | | Options Id | Description | Type | Default Value |
|-----|-----|-----|-----| |-----|-----|-----|-----|
| version | Select or enter an Azure CLI version. (Available versions may vary by Linux distribution.) | string | latest | | version | Select or enter an Azure CLI version. (Available versions may vary by Linux distribution.) | string | latest |
| extensions | Optional comma separated list of Azure CLI extensions to install in profile. | string | - |
| installBicep | Optionally install Azure Bicep | boolean | false |
| installUsingPython | Install Azure CLI using Python instead of pipx | boolean | false |
## Customizations
### VS Code Extensions
- `ms-vscode.azurecli`
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.
--- ---

View file

@ -1,6 +1,6 @@
{ {
"id": "azure-cli", "id": "azure-cli",
"version": "1.0.3", "version": "1.2.2",
"name": "Azure CLI", "name": "Azure CLI",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/azure-cli", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/azure-cli",
"description": "Installs the Azure CLI along with needed dependencies. Useful for base Dockerfiles that often are missing required install dependencies like gpg.", "description": "Installs the Azure CLI along with needed dependencies. Useful for base Dockerfiles that often are missing required install dependencies like gpg.",
@ -12,13 +12,31 @@
], ],
"default": "latest", "default": "latest",
"description": "Select or enter an Azure CLI version. (Available versions may vary by Linux distribution.)" "description": "Select or enter an Azure CLI version. (Available versions may vary by Linux distribution.)"
},
"extensions": {
"type": "string",
"default": "",
"description": "Optional comma separated list of Azure CLI extensions to install in profile."
},
"installBicep": {
"type": "boolean",
"description": "Optionally install Azure Bicep",
"default": false
},
"installUsingPython": {
"type": "boolean",
"description": "Install Azure CLI using Python instead of pipx",
"default": false
} }
}, },
"customizations": { "customizations": {
"vscode": { "vscode": {
"extensions": [ "extensions": [
"ms-vscode.azurecli" "ms-vscode.azurecli"
] ]
} }
} },
} "installsAfter": [
"ghcr.io/devcontainers/features/common-utils"
]
}

View file

@ -9,8 +9,13 @@
set -e set -e
AZ_VERSION=${VERSION:-"latest"} # Clean up
rm -rf /var/lib/apt/lists/*
AZ_VERSION=${VERSION:-"latest"}
AZ_EXTENSIONS=${EXTENSIONS}
AZ_INSTALLBICEP=${INSTALLBICEP:-false}
INSTALL_USING_PYTHON=${INSTALL_USING_PYTHON:-true}
MICROSOFT_GPG_KEYS_URI="https://packages.microsoft.com/keys/microsoft.asc" MICROSOFT_GPG_KEYS_URI="https://packages.microsoft.com/keys/microsoft.asc"
AZCLI_ARCHIVE_ARCHITECTURES="amd64" AZCLI_ARCHIVE_ARCHITECTURES="amd64"
AZCLI_ARCHIVE_VERSION_CODENAMES="stretch buster bullseye bionic focal jammy" AZCLI_ARCHIVE_VERSION_CODENAMES="stretch buster bullseye bionic focal jammy"
@ -20,20 +25,12 @@ if [ "$(id -u)" -ne 0 ]; then
exit 1 exit 1
fi fi
# Get central common setting if [ -z "${_REMOTE_USER}" ]; then
get_common_setting() { echo -e 'Feature script must be executed by a tool that implements the dev container specification. See https://containers.dev/ for more information.'
if [ "${common_settings_file_loaded}" != "true" ]; then exit 1
curl -sfL "https://aka.ms/vscode-dev-containers/script-library/settings.env" 2>/dev/null -o /tmp/vsdc-settings.env || echo "Could not download settings file. Skipping." fi
common_settings_file_loaded=true
fi echo "Effective REMOTE_USER: ${_REMOTE_USER}"
if [ -f "/tmp/vsdc-settings.env" ]; then
local multi_line=""
if [ "$2" = "true" ]; then multi_line="-z"; fi
local result="$(grep ${multi_line} -oP "$1=\"?\K[^\"]+" /tmp/vsdc-settings.env | tr -d '\0')"
if [ ! -z "${result}" ]; then declare -g $1="${result}"; fi
fi
echo "$1=${!1}"
}
apt_get_update() apt_get_update()
{ {
@ -44,13 +41,14 @@ apt_get_update()
# Checks if packages are installed and installs them if not # Checks if packages are installed and installs them if not
check_packages() { check_packages() {
if ! dpkg -s "$@" > /dev/null 2>&1; then if ! dpkg -s "$@" > /dev/null 2>&1; then
apt_get_update if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then
echo "Running apt-get update..."
apt-get update -y
fi
apt-get -y install --no-install-recommends "$@" apt-get -y install --no-install-recommends "$@"
fi fi
} }
export DEBIAN_FRONTEND=noninteractive
# Soft version matching that resolves a version for a given package in the *current apt-cache* # Soft version matching that resolves a version for a given package in the *current apt-cache*
# Return value is stored in first argument (the unprocessed version) # Return value is stored in first argument (the unprocessed version)
apt_cache_version_soft_match() { apt_cache_version_soft_match() {
@ -97,7 +95,6 @@ install_using_apt() {
# Install dependencies # Install dependencies
check_packages apt-transport-https curl ca-certificates gnupg2 dirmngr check_packages apt-transport-https curl ca-certificates gnupg2 dirmngr
# Import key safely (new 'signed-by' method rather than deprecated apt-key approach) and install # Import key safely (new 'signed-by' method rather than deprecated apt-key approach) and install
get_common_setting MICROSOFT_GPG_KEYS_URI
curl -sSL ${MICROSOFT_GPG_KEYS_URI} | gpg --dearmor > /usr/share/keyrings/microsoft-archive-keyring.gpg curl -sSL ${MICROSOFT_GPG_KEYS_URI} | gpg --dearmor > /usr/share/keyrings/microsoft-archive-keyring.gpg
echo "deb [arch=${architecture} signed-by=/usr/share/keyrings/microsoft-archive-keyring.gpg] https://packages.microsoft.com/repos/azure-cli/ ${VERSION_CODENAME} main" > /etc/apt/sources.list.d/azure-cli.list echo "deb [arch=${architecture} signed-by=/usr/share/keyrings/microsoft-archive-keyring.gpg] https://packages.microsoft.com/repos/azure-cli/ ${VERSION_CODENAME} main" > /etc/apt/sources.list.d/azure-cli.list
apt-get update apt-get update
@ -119,7 +116,43 @@ install_using_apt() {
fi fi
} }
install_using_pip() { install_using_pip_strategy() {
local ver=""
if [ "${AZ_VERSION}" = "latest" ] || [ "${AZ_VERSION}" = "lts" ] || [ "${AZ_VERSION}" = "stable" ]; then
# Empty, meaning grab the "latest" in the apt repo
ver=""
else
ver="==${AZ_VERSION}"
fi
if [ "${INSTALL_USING_PYTHON}" = "true" ]; then
install_with_complete_python_installation "${ver}" || install_with_pipx "${ver}" || return 1
else
install_with_pipx "${ver}" || install_with_complete_python_installation "${ver}" || return 1
fi
}
install_with_pipx() {
echo "(*) Attempting to install globally with pipx..."
local ver="$1"
export
local
if ! type pipx > /dev/null 2>&1; then
echo "(*) Installing pipx..."
check_packages pipx
pipx ensurepath # Ensures PIPX_BIN_DIR is on the PATH
fi
PIPX_HOME="/usr/local/pipx" \
PIPX_BIN_DIR=/usr/local/bin \
pipx install azure-cli${ver}
echo "(*) Finished installing globally with pipx."
}
install_with_complete_python_installation() {
local ver="$1"
echo "(*) No pre-built binaries available in apt-cache. Installing via pip3." echo "(*) No pre-built binaries available in apt-cache. Installing via pip3."
if ! dpkg -s python3-minimal python3-pip libffi-dev python3-venv > /dev/null 2>&1; then if ! dpkg -s python3-minimal python3-pip libffi-dev python3-venv > /dev/null 2>&1; then
apt_get_update apt_get_update
@ -136,25 +169,20 @@ install_using_pip() {
pipx_bin=/tmp/pip-tmp/bin/pipx pipx_bin=/tmp/pip-tmp/bin/pipx
fi fi
if [ "${AZ_VERSION}" = "latest" ] || [ "${AZ_VERSION}" = "lts" ] || [ "${AZ_VERSION}" = "stable" ]; then
# Empty, meaning grab the "latest" in the apt repo
ver=""
else
ver="==${AZ_VERSION}"
fi
set +e set +e
${pipx_bin} install --pip-args '--no-cache-dir --force-reinstall' -f azure-cli${ver} ${pipx_bin} install --pip-args '--no-cache-dir --force-reinstall' -f azure-cli${ver}
# Fail gracefully # Fail gracefully
if [ "$?" != 0 ]; then if [ "$?" != 0 ]; then
echo "Could not install azure-cli${ver} via pip" echo "Could not install azure-cli${ver} via pip3"
rm -rf /tmp/pip-tmp rm -rf /tmp/pip-tmp
return 1 return 1
fi fi
set -e set -e
} }
export DEBIAN_FRONTEND=noninteractive
# See if we're on x86_64 and if so, install via apt-get, otherwise use pip3 # See if we're on x86_64 and if so, install via apt-get, otherwise use pip3
echo "(*) Installing Azure CLI..." echo "(*) Installing Azure CLI..."
. /etc/os-release . /etc/os-release
@ -168,7 +196,7 @@ fi
if [ "${use_pip}" = "true" ]; then if [ "${use_pip}" = "true" ]; then
AZ_VERSION=${CACHED_AZURE_VERSION} AZ_VERSION=${CACHED_AZURE_VERSION}
install_using_pip install_using_pip_strategy
if [ "$?" != 0 ]; then if [ "$?" != 0 ]; then
echo "Please provide a valid version for your distribution ${ID} ${VERSION_CODENAME} (${architecture})." echo "Please provide a valid version for your distribution ${ID} ${VERSION_CODENAME} (${architecture})."
@ -179,4 +207,42 @@ if [ "${use_pip}" = "true" ]; then
fi fi
fi fi
echo "Done!" # If Azure CLI extensions are requested, loop through and install
if [ ${#AZ_EXTENSIONS[@]} -gt 0 ]; then
echo "Installing Azure CLI extensions: ${AZ_EXTENSIONS}"
extensions=(`echo ${AZ_EXTENSIONS} | tr ',' ' '`)
for i in "${extensions[@]}"
do
echo "Installing ${i}"
su ${_REMOTE_USER} -c "az extension add --name ${i} -y" || continue
done
fi
if [ "${AZ_INSTALLBICEP}" = "true" ]; then
# Install dependencies
check_packages apt-transport-https curl
# Properly install Azure Bicep based on current architecture
# The `az bicep install` command installs the linux-x64 binary even on arm64 devcontainers
# The `az bicep install --target-platform` could be a solution; however, linux-arm64 is not an allowed value for this argument yet
# Manually installing Bicep and moving to the appropriate directory where az expects it to be
if [ "${architecture}" = "arm64" ]; then
curl -Lo bicep https://github.com/Azure/bicep/releases/latest/download/bicep-linux-arm64
else
curl -Lo bicep https://github.com/Azure/bicep/releases/latest/download/bicep-linux-x64
fi
chmod +x ./bicep
mv ./bicep /usr/local/bin/bicep
# Add a symlink so bicep can be accessed as a standalone executable or as part of az
mkdir -p ${_REMOTE_USER_HOME}/.azure/bin
chown -hR ${_REMOTE_USER}:${_REMOTE_USER} ${_REMOTE_USER_HOME}/.azure
ln -s /usr/local/bin/bicep ${_REMOTE_USER_HOME}/.azure/bin/bicep
fi
# Clean up
rm -rf /var/lib/apt/lists/*
echo "Done!"

View file

@ -1,12 +1,26 @@
## Speeding up the command prompt in large repositories ## OS Support
This script provides a custom command prompt that includes information about the git repository for the current folder. However, with certain large repositories, this can result in a slow command prompt since the required git status command can be slow. To resolve this, you can update a git setting to remove the git portion of the command prompt. This Feature should work on recent versions of Debian/Ubuntu, RedHat Enterprise Linux, Fedora, RockyLinux, and Alpine Linux.
To disable the prompt for the current folder's repository, enter the following in a terminal or add it to your `postCreateCommand` or dotfiles: ## Using with dev container images
This Feature is used in many of the [dev container images](https://github.com/search?q=repo%3Adevcontainers%2Fimages+%22ghcr.io%2Fdevcontainers%2Ffeatures%2Fcommon-utils%22&type=code), as a result
these images have already allocated UID & GID 1000. Attempting to add this Feature with UID 1000 and/or GID 1000 on top of such a dev container image will result in an error when building the dev container.
## Customizing the command prompt
By default, this script provides a custom command prompt that includes information about the git repository for the current folder. However, with certain large repositories, this can result in a slow command prompt due to the performance of needed git operations.
For performance reasons, a "dirty" indicator that tells you whether or not there are uncommitted changes is disabled by default. You can opt to turn this on for smaller repositories by entering the following in a terminal or adding it to your `postCreateCommand`:
```bash ```bash
git config codespaces-theme.hide-status 1 git config devcontainers-theme.show-dirty 1
``` ```
This setting will survive a rebuild since it is applied to the repository rather than the container. To completely disable the git portion of the prompt for the current folder's repository, you can use this configuration setting instead:
```bash
git config devcontainers-theme.hide-status 1
```
For `zsh`, the default theme is a [standard Oh My Zsh! theme](https://ohmyz.sh/). You may pick a different one by modifying the `ZSH_THEME` variable in `~/.zshrc`.

View file

@ -1,5 +1,5 @@
# Common Debian Utilities (common-utils) # Common Utilities (common-utils)
Installs a set of common command line utilities, Oh My Zsh!, and sets up a non-root user. Installs a set of common command line utilities, Oh My Zsh!, and sets up a non-root user.
@ -7,9 +7,7 @@ Installs a set of common command line utilities, Oh My Zsh!, and sets up a non-r
```json ```json
"features": { "features": {
"ghcr.io/devcontainers/features/common-utils:1": { "ghcr.io/devcontainers/features/common-utils:2": {}
"version": "latest"
}
} }
``` ```
@ -18,25 +16,41 @@ Installs a set of common command line utilities, Oh My Zsh!, and sets up a non-r
| Options Id | Description | Type | Default Value | | Options Id | Description | Type | Default Value |
|-----|-----|-----|-----| |-----|-----|-----|-----|
| installZsh | Install ZSH? | boolean | true | | installZsh | Install ZSH? | boolean | true |
| configureZshAsDefaultShell | Change default shell to ZSH? | boolean | false |
| installOhMyZsh | Install Oh My Zsh!? | boolean | true | | installOhMyZsh | Install Oh My Zsh!? | boolean | true |
| installOhMyZshConfig | Allow installing the default dev container .zshrc templates? | boolean | true |
| upgradePackages | Upgrade OS packages? | boolean | true | | upgradePackages | Upgrade OS packages? | boolean | true |
| username | Enter name of non-root user to configure or none to skip | string | automatic | | username | Enter name of a non-root user to configure or none to skip | string | automatic |
| uid | Enter uid for non-root user | string | automatic | | userUid | Enter UID for non-root user | string | automatic |
| gid | Enter gid for non-root user | string | automatic | | userGid | Enter GID for non-root user | string | automatic |
| nonFreePackages | Add packages from non-free Debian repository? | boolean | - | | nonFreePackages | Add packages from non-free Debian repository? (Debian only) | boolean | false |
## Speeding up the command prompt in large repositories ## OS Support
This script provides a custom command prompt that includes information about the git repository for the current folder. However, with certain large repositories, this can result in a slow command prompt since the required git status command can be slow. To resolve this, you can update a git setting to remove the git portion of the command prompt. This Feature should work on recent versions of Debian/Ubuntu, RedHat Enterprise Linux, Fedora, RockyLinux, and Alpine Linux.
To disable the prompt for the current folder's repository, enter the following in a terminal or add it to your `postCreateCommand` or dotfiles: ## Using with dev container images
This Feature is used in many of the [dev container images](https://github.com/search?q=repo%3Adevcontainers%2Fimages+%22ghcr.io%2Fdevcontainers%2Ffeatures%2Fcommon-utils%22&type=code), as a result
these images have already allocated UID & GID 1000. Attempting to add this Feature with UID 1000 and/or GID 1000 on top of such a dev container image will result in an error when building the dev container.
## Customizing the command prompt
By default, this script provides a custom command prompt that includes information about the git repository for the current folder. However, with certain large repositories, this can result in a slow command prompt due to the performance of needed git operations.
For performance reasons, a "dirty" indicator that tells you whether or not there are uncommitted changes is disabled by default. You can opt to turn this on for smaller repositories by entering the following in a terminal or adding it to your `postCreateCommand`:
```bash ```bash
git config codespaces-theme.hide-status 1 git config devcontainers-theme.show-dirty 1
``` ```
This setting will survive a rebuild since it is applied to the repository rather than the container. To completely disable the git portion of the prompt for the current folder's repository, you can use this configuration setting instead:
```bash
git config devcontainers-theme.hide-status 1
```
For `zsh`, the default theme is a [standard Oh My Zsh! theme](https://ohmyz.sh/). You may pick a different one by modifying the `ZSH_THEME` variable in `~/.zshrc`.
--- ---

16
src/common-utils/bin/code Executable file
View file

@ -0,0 +1,16 @@
#!/bin/sh
get_in_path_except_current() {
which -a "$1" | grep -A1 "$0" | grep -v "$0"
}
code="$(get_in_path_except_current code)"
if [ -n "$code" ]; then
exec "$code" "$@"
elif [ "$(command -v code-insiders)" ]; then
exec code-insiders "$@"
else
echo "code or code-insiders is not installed" >&2
exit 127
fi

View file

@ -0,0 +1,35 @@
#!/bin/sh
# Load meta.env
if [ -f "/usr/local/etc/vscode-dev-containers/meta.env" ]; then
. /usr/local/etc/vscode-dev-containers/meta.env
fi
if [ -f "/usr/local/etc/dev-containers/meta.env" ]; then
. /usr/local/etc/dev-containers/meta.env
fi
# Minimal output
if [ "$1" = "version" ] || [ "$1" = "image-version" ]; then
echo "${VERSION}"
exit 0
elif [ "$1" = "release" ]; then
echo "${GIT_REPOSITORY_RELEASE}"
exit 0
elif [ "$1" = "content" ] || [ "$1" = "content-url" ] || [ "$1" = "contents" ] || [ "$1" = "contents-url" ]; then
echo "${CONTENTS_URL}"
exit 0
fi
#Full output
echo
echo "Development container image information"
echo
if [ ! -z "${VERSION}" ]; then echo "- Image version: ${VERSION}"; fi
if [ ! -z "${DEFINITION_ID}" ]; then echo "- Definition ID: ${DEFINITION_ID}"; fi
if [ ! -z "${VARIANT}" ]; then echo "- Variant: ${VARIANT}"; fi
if [ ! -z "${GIT_REPOSITORY}" ]; then echo "- Source code repository: ${GIT_REPOSITORY}"; fi
if [ ! -z "${GIT_REPOSITORY_RELEASE}" ]; then echo "- Source code release/branch: ${GIT_REPOSITORY_RELEASE}"; fi
if [ ! -z "${GIT_REPOSITORY_REVISION}" ]; then echo "- Source code revision: ${GIT_REPOSITORY_REVISION}"; fi
if [ ! -z "${BUILD_TIMESTAMP}" ]; then echo "- Timestamp: ${BUILD_TIMESTAMP}"; fi
if [ ! -z "${CONTENTS_URL}" ]; then echo && echo "More info: ${CONTENTS_URL}"; fi
echo

7
src/common-utils/bin/systemctl Executable file
View file

@ -0,0 +1,7 @@
#!/bin/sh
set -e
if [ -d "/run/systemd/system" ]; then
exec /bin/systemctl "$@"
else
echo '\n"systemd" is not running in this container due to its overhead.\nUse the "service" command to start services instead. e.g.: \n\nservice --status-all'
fi

View file

@ -1,7 +1,7 @@
{ {
"id": "common-utils", "id": "common-utils",
"version": "1.1.1", "version": "2.3.1",
"name": "Common Debian Utilities", "name": "Common Utilities",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/common-utils", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/common-utils",
"description": "Installs a set of common command line utilities, Oh My Zsh!, and sets up a non-root user.", "description": "Installs a set of common command line utilities, Oh My Zsh!, and sets up a non-root user.",
"options": { "options": {
@ -10,11 +10,21 @@
"default": true, "default": true,
"description": "Install ZSH?" "description": "Install ZSH?"
}, },
"configureZshAsDefaultShell": {
"type": "boolean",
"default": false,
"description": "Change default shell to ZSH?"
},
"installOhMyZsh": { "installOhMyZsh": {
"type": "boolean", "type": "boolean",
"default": true, "default": true,
"description": "Install Oh My Zsh!?" "description": "Install Oh My Zsh!?"
}, },
"installOhMyZshConfig": {
"type": "boolean",
"default": true,
"description": "Allow installing the default dev container .zshrc templates?"
},
"upgradePackages": { "upgradePackages": {
"type": "boolean", "type": "boolean",
"default": true, "default": true,
@ -23,36 +33,37 @@
"username": { "username": {
"type": "string", "type": "string",
"proposals": [ "proposals": [
"devcontainer",
"vscode", "vscode",
"codespace", "codespace",
"none", "none",
"automatic" "automatic"
], ],
"default": "automatic", "default": "automatic",
"description": "Enter name of non-root user to configure or none to skip" "description": "Enter name of a non-root user to configure or none to skip"
}, },
"uid": { "userUid": {
"type": "string", "type": "string",
"proposals": [ "proposals": [
"1000", "1001",
"automatic" "automatic"
], ],
"default": "automatic", "default": "automatic",
"description": "Enter uid for non-root user" "description": "Enter UID for non-root user"
}, },
"gid": { "userGid": {
"type": "string", "type": "string",
"proposals": [ "proposals": [
"1000", "1001",
"automatic" "automatic"
], ],
"default": "automatic", "default": "automatic",
"description": "Enter gid for non-root user" "description": "Enter GID for non-root user"
}, },
"nonFreePackages": { "nonFreePackages": {
"type": "boolean", "type": "boolean",
"default": false, "default": false,
"description": "Add packages from non-free Debian repository?" "description": "Add packages from non-free Debian repository? (Debian only)"
} }
} }
} }

View file

@ -1,452 +1,36 @@
#!/usr/bin/env bash #!/bin/sh
#------------------------------------------------------------------------------------------------------------- #-------------------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved. # Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. # Licensed under the MIT License. See https://github.com/devcontainers/features/blob/main/LICENSE for license information.
#------------------------------------------------------------------------------------------------------------- #-------------------------------------------------------------------------------------------------------------------------
# #
# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/common.md # Docs: https://github.com/devcontainers/features/tree/main/src/common-utils
# Maintainer: The VS Code and Codespaces Teams # Maintainer: The Dev Container spec maintainers
set -e set -e
INSTALL_ZSH=${INSTALLZSH:-"true"} INSTALL_ZSH="${INSTALLZSH:-"true"}"
INSTALL_OH_MY_ZSH=${INSTALLOHMYZSH:-"true"} CONFIGURE_ZSH_AS_DEFAULT_SHELL="${CONFIGUREZSHASDEFAULTSHELL:-"false"}"
UPGRADE_PACKAGES=${UPGRADEPACKAGES:-"true"} INSTALL_OH_MY_ZSH="${INSTALLOHMYZSH:-"true"}"
USERNAME=${USERNAME:-"automatic"} INSTALL_OH_MY_ZSH_CONFIG="${INSTALLOHMYZSHCONFIG:-"true"}"
USER_UID=${UID:-"automatic"} UPGRADE_PACKAGES="${UPGRADEPACKAGES:-"true"}"
USER_GID=${GID:-"automatic"} USERNAME="${USERNAME:-"automatic"}"
ADD_NON_FREE_PACKAGES=${NONFREEPACKAGES:-"false"} USER_UID="${UID:-"automatic"}"
USER_GID="${GID:-"automatic"}"
DEV_CONTAINERS_DIR="/usr/local/etc/vscode-dev-containers" ADD_NON_FREE_PACKAGES="${NONFREEPACKAGES:-"false"}"
MARKER_FILE="${DEV_CONTAINERS_DIR}/common"
MARKER_FILE="/usr/local/etc/vscode-dev-containers/common"
if [ "$(id -u)" -ne 0 ]; then if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1 exit 1
fi fi
# Ensure that login shells get the correct path if the user updated the PATH using ENV. # If we're using Alpine, install bash before executing
rm -f /etc/profile.d/00-restore-env.sh . /etc/os-release
echo "export PATH=${PATH//$(sh -lc 'echo $PATH')/\$PATH}" > /etc/profile.d/00-restore-env.sh if [ "${ID}" = "alpine" ]; then
chmod +x /etc/profile.d/00-restore-env.sh apk add --no-cache bash
# If in automatic mode, determine if a user already exists, if not use vscode
if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then
USERNAME=""
POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)")
for CURRENT_USER in "${POSSIBLE_USERS[@]}"; do
if id -u ${CURRENT_USER} > /dev/null 2>&1; then
USERNAME=${CURRENT_USER}
break
fi
done
if [ "${USERNAME}" = "" ]; then
USERNAME=vscode
fi
elif [ "${USERNAME}" = "none" ]; then
USERNAME=root
USER_UID=0
USER_GID=0
fi fi
# Load markers to see which steps have already run exec /bin/bash "$(dirname $0)/main.sh" "$@"
if [ -f "${MARKER_FILE}" ]; then exit $?
echo "Marker file found:"
cat "${MARKER_FILE}"
source "${MARKER_FILE}"
fi
# Ensure apt is in non-interactive to avoid prompts
export DEBIAN_FRONTEND=noninteractive
apt_get_update()
{
echo "Running apt-get update..."
apt-get update -y
}
# Run install apt-utils to avoid debconf warning then verify presence of other common developer tools and dependencies
if [ "${PACKAGES_ALREADY_INSTALLED}" != "true" ]; then
package_list="apt-utils \
openssh-client \
gnupg2 \
dirmngr \
iproute2 \
procps \
lsof \
htop \
net-tools \
psmisc \
curl \
tree \
wget \
rsync \
ca-certificates \
unzip \
bzip2 \
zip \
nano \
vim-tiny \
less \
jq \
lsb-release \
apt-transport-https \
dialog \
libc6 \
libgcc1 \
libkrb5-3 \
libgssapi-krb5-2 \
libicu[0-9][0-9] \
liblttng-ust[0-9] \
libstdc++6 \
zlib1g \
locales \
sudo \
ncdu \
man-db \
strace \
manpages \
manpages-dev \
init-system-helpers"
# Needed for adding manpages-posix and manpages-posix-dev which are non-free packages in Debian
if [ "${ADD_NON_FREE_PACKAGES}" = "true" ]; then
# Bring in variables from /etc/os-release like VERSION_CODENAME
. /etc/os-release
sed -i -E "s/deb http:\/\/(deb|httpredir)\.debian\.org\/debian ${VERSION_CODENAME} main/deb http:\/\/\1\.debian\.org\/debian ${VERSION_CODENAME} main contrib non-free/" /etc/apt/sources.list
sed -i -E "s/deb-src http:\/\/(deb|httredir)\.debian\.org\/debian ${VERSION_CODENAME} main/deb http:\/\/\1\.debian\.org\/debian ${VERSION_CODENAME} main contrib non-free/" /etc/apt/sources.list
sed -i -E "s/deb http:\/\/(deb|httpredir)\.debian\.org\/debian ${VERSION_CODENAME}-updates main/deb http:\/\/\1\.debian\.org\/debian ${VERSION_CODENAME}-updates main contrib non-free/" /etc/apt/sources.list
sed -i -E "s/deb-src http:\/\/(deb|httpredir)\.debian\.org\/debian ${VERSION_CODENAME}-updates main/deb http:\/\/\1\.debian\.org\/debian ${VERSION_CODENAME}-updates main contrib non-free/" /etc/apt/sources.list
sed -i "s/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}\/updates main/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}\/updates main contrib non-free/" /etc/apt/sources.list
sed -i "s/deb-src http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}\/updates main/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}\/updates main contrib non-free/" /etc/apt/sources.list
sed -i "s/deb http:\/\/deb\.debian\.org\/debian ${VERSION_CODENAME}-backports main/deb http:\/\/deb\.debian\.org\/debian ${VERSION_CODENAME}-backports main contrib non-free/" /etc/apt/sources.list
sed -i "s/deb-src http:\/\/deb\.debian\.org\/debian ${VERSION_CODENAME}-backports main/deb http:\/\/deb\.debian\.org\/debian ${VERSION_CODENAME}-backports main contrib non-free/" /etc/apt/sources.list
# Handle bullseye location for security https://www.debian.org/releases/bullseye/amd64/release-notes/ch-information.en.html
sed -i "s/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}-security main/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}-security main contrib non-free/" /etc/apt/sources.list
sed -i "s/deb-src http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}-security main/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}-security main contrib non-free/" /etc/apt/sources.list
echo "Running apt-get update..."
apt-get update
package_list="${package_list} manpages-posix manpages-posix-dev"
else
apt_get_update
fi
# Install libssl1.1 if available
if [[ ! -z $(apt-cache --names-only search ^libssl1.1$) ]]; then
package_list="${package_list} libssl1.1"
fi
# Install appropriate version of libssl1.0.x if available
libssl_package=$(dpkg-query -f '${db:Status-Abbrev}\t${binary:Package}\n' -W 'libssl1\.0\.?' 2>&1 || echo '')
if [ "$(echo "$LIlibssl_packageBSSL" | grep -o 'libssl1\.0\.[0-9]:' | uniq | sort | wc -l)" -eq 0 ]; then
if [[ ! -z $(apt-cache --names-only search ^libssl1.0.2$) ]]; then
# Debian 9
package_list="${package_list} libssl1.0.2"
elif [[ ! -z $(apt-cache --names-only search ^libssl1.0.0$) ]]; then
# Ubuntu 18.04, 16.04, earlier
package_list="${package_list} libssl1.0.0"
fi
fi
echo "Packages to verify are installed: ${package_list}"
apt-get -y install --no-install-recommends ${package_list} 2> >( grep -v 'debconf: delaying package configuration, since apt-utils is not installed' >&2 )
# Install git if not already installed (may be more recent than distro version)
if ! type git > /dev/null 2>&1; then
apt-get -y install --no-install-recommends git
fi
PACKAGES_ALREADY_INSTALLED="true"
fi
# Get to latest versions of all packages
if [ "${UPGRADE_PACKAGES}" = "true" ]; then
apt_get_update
apt-get -y upgrade --no-install-recommends
apt-get autoremove -y
fi
# Ensure at least the en_US.UTF-8 UTF-8 locale is available.
# Common need for both applications and things like the agnoster ZSH theme.
if [ "${LOCALE_ALREADY_SET}" != "true" ] && ! grep -o -E '^\s*en_US.UTF-8\s+UTF-8' /etc/locale.gen > /dev/null; then
echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen
locale-gen
LOCALE_ALREADY_SET="true"
fi
# Create or update a non-root user to match UID/GID.
group_name="${USERNAME}"
if id -u ${USERNAME} > /dev/null 2>&1; then
# User exists, update if needed
if [ "${USER_GID}" != "automatic" ] && [ "$USER_GID" != "$(id -g $USERNAME)" ]; then
group_name="$(id -gn $USERNAME)"
groupmod --gid $USER_GID ${group_name}
usermod --gid $USER_GID $USERNAME
fi
if [ "${USER_UID}" != "automatic" ] && [ "$USER_UID" != "$(id -u $USERNAME)" ]; then
usermod --uid $USER_UID $USERNAME
fi
else
# Create user
if [ "${USER_GID}" = "automatic" ]; then
groupadd $USERNAME
else
groupadd --gid $USER_GID $USERNAME
fi
if [ "${USER_UID}" = "automatic" ]; then
useradd -s /bin/bash --gid $USERNAME -m $USERNAME
else
useradd -s /bin/bash --uid $USER_UID --gid $USERNAME -m $USERNAME
fi
fi
# Add add sudo support for non-root user
if [ "${USERNAME}" != "root" ] && [ "${EXISTING_NON_ROOT_USER}" != "${USERNAME}" ]; then
echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME
chmod 0440 /etc/sudoers.d/$USERNAME
EXISTING_NON_ROOT_USER="${USERNAME}"
fi
# ** Shell customization section **
if [ "${USERNAME}" = "root" ]; then
user_rc_path="/root"
else
user_rc_path="/home/${USERNAME}"
fi
# Restore user .bashrc defaults from skeleton file if it doesn't exist or is empty
if [ ! -f "${user_rc_path}/.bashrc" ] || [ ! -s "${user_rc_path}/.bashrc" ] ; then
cp /etc/skel/.bashrc "${user_rc_path}/.bashrc"
fi
# Restore user .profile defaults from skeleton file if it doesn't exist or is empty
if [ ! -f "${user_rc_path}/.profile" ] || [ ! -s "${user_rc_path}/.profile" ] ; then
cp /etc/skel/.profile "${user_rc_path}/.profile"
fi
# .bashrc/.zshrc snippet
rc_snippet="$(cat << 'EOF'
if [ -z "${USER}" ]; then export USER=$(whoami); fi
if [[ "${PATH}" != *"$HOME/.local/bin"* ]]; then export PATH="${PATH}:$HOME/.local/bin"; fi
# Display optional first run image specific notice if configured and terminal is interactive
if [ -t 1 ] && [[ "${TERM_PROGRAM}" = "vscode" || "${TERM_PROGRAM}" = "codespaces" ]] && [ ! -f "$HOME/.config/vscode-dev-containers/first-run-notice-already-displayed" ]; then
if [ -f "${DEV_CONTAINERS_DIR}/first-run-notice.txt" ]; then
cat "${DEV_CONTAINERS_DIR}/first-run-notice.txt"
elif [ -f "/workspaces/.codespaces/shared/first-run-notice.txt" ]; then
cat "/workspaces/.codespaces/shared/first-run-notice.txt"
fi
mkdir -p "$HOME/.config/vscode-dev-containers"
# Mark first run notice as displayed after 10s to avoid problems with fast terminal refreshes hiding it
((sleep 10s; touch "$HOME/.config/vscode-dev-containers/first-run-notice-already-displayed") &)
fi
# Set the default git editor if not already set
if [ -z "$(git config --get core.editor)" ] && [ -z "${GIT_EDITOR}" ]; then
if [ "${TERM_PROGRAM}" = "vscode" ]; then
if [[ -n $(command -v code-insiders) && -z $(command -v code) ]]; then
export GIT_EDITOR="code-insiders --wait"
else
export GIT_EDITOR="code --wait"
fi
fi
fi
EOF
)"
# code shim, it fallbacks to code-insiders if code is not available
cat << 'EOF' > /usr/local/bin/code
#!/bin/sh
get_in_path_except_current() {
which -a "$1" | grep -A1 "$0" | grep -v "$0"
}
code="$(get_in_path_except_current code)"
if [ -n "$code" ]; then
exec "$code" "$@"
elif [ "$(command -v code-insiders)" ]; then
exec code-insiders "$@"
else
echo "code or code-insiders is not installed" >&2
exit 127
fi
EOF
chmod +x /usr/local/bin/code
# systemctl shim - tells people to use 'service' if systemd is not running
cat << 'EOF' > /usr/local/bin/systemctl
#!/bin/sh
set -e
if [ -d "/run/systemd/system" ]; then
exec /bin/systemctl/systemctl "$@"
else
echo '\n"systemd" is not running in this container due to its overhead.\nUse the "service" command to start services instead. e.g.: \n\nservice --status-all'
fi
EOF
chmod +x /usr/local/bin/systemctl
# Codespaces bash and OMZ themes - partly inspired by https://github.com/ohmyzsh/ohmyzsh/blob/master/themes/robbyrussell.zsh-theme
codespaces_bash="$(cat \
<<'EOF'
# Codespaces bash prompt theme
__bash_prompt() {
local userpart='`export XIT=$? \
&& [ ! -z "${GITHUB_USER}" ] && echo -n "\[\033[0;32m\]@${GITHUB_USER} " || echo -n "\[\033[0;32m\]\u " \
&& [ "$XIT" -ne "0" ] && echo -n "\[\033[1;31m\]➜" || echo -n "\[\033[0m\]➜"`'
local gitbranch='`\
if [ "$(git config --get codespaces-theme.hide-status 2>/dev/null)" != 1 ]; then \
export BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null || git rev-parse --short HEAD 2>/dev/null); \
if [ "${BRANCH}" != "" ]; then \
echo -n "\[\033[0;36m\](\[\033[1;31m\]${BRANCH}" \
&& if git ls-files --error-unmatch -m --directory --no-empty-directory -o --exclude-standard ":/*" > /dev/null 2>&1; then \
echo -n " \[\033[1;33m\]✗"; \
fi \
&& echo -n "\[\033[0;36m\]) "; \
fi; \
fi`'
local lightblue='\[\033[1;34m\]'
local removecolor='\[\033[0m\]'
PS1="${userpart} ${lightblue}\w ${gitbranch}${removecolor}\$ "
unset -f __bash_prompt
}
__bash_prompt
EOF
)"
codespaces_zsh="$(cat \
<<'EOF'
# Codespaces zsh prompt theme
__zsh_prompt() {
local prompt_username
if [ ! -z "${GITHUB_USER}" ]; then
prompt_username="@${GITHUB_USER}"
else
prompt_username="%n"
fi
PROMPT="%{$fg[green]%}${prompt_username} %(?:%{$reset_color%}➜ :%{$fg_bold[red]%}➜ )" # User/exit code arrow
PROMPT+='%{$fg_bold[blue]%}%(5~|%-1~/…/%3~|%4~)%{$reset_color%} ' # cwd
PROMPT+='$([ "$(git config --get codespaces-theme.hide-status 2>/dev/null)" != 1 ] && git_prompt_info)' # Git status
PROMPT+='%{$fg[white]%}$ %{$reset_color%}'
unset -f __zsh_prompt
}
ZSH_THEME_GIT_PROMPT_PREFIX="%{$fg_bold[cyan]%}(%{$fg_bold[red]%}"
ZSH_THEME_GIT_PROMPT_SUFFIX="%{$reset_color%} "
ZSH_THEME_GIT_PROMPT_DIRTY=" %{$fg_bold[yellow]%}✗%{$fg_bold[cyan]%})"
ZSH_THEME_GIT_PROMPT_CLEAN="%{$fg_bold[cyan]%})"
__zsh_prompt
EOF
)"
# Add RC snippet and custom bash prompt
if [ "${RC_SNIPPET_ALREADY_ADDED}" != "true" ]; then
echo "${rc_snippet}" >> /etc/bash.bashrc
echo "${codespaces_bash}" >> "${user_rc_path}/.bashrc"
echo 'export PROMPT_DIRTRIM=4' >> "${user_rc_path}/.bashrc"
if [ "${USERNAME}" != "root" ]; then
echo "${codespaces_bash}" >> "/root/.bashrc"
echo 'export PROMPT_DIRTRIM=4' >> "/root/.bashrc"
fi
chown ${USERNAME}:${group_name} "${user_rc_path}/.bashrc"
RC_SNIPPET_ALREADY_ADDED="true"
fi
# Optionally install and configure zsh and Oh My Zsh!
if [ "${INSTALL_ZSH}" = "true" ]; then
if ! type zsh > /dev/null 2>&1; then
apt_get_update
apt-get install -y zsh
fi
if [ "${ZSH_ALREADY_INSTALLED}" != "true" ]; then
echo "${rc_snippet}" >> /etc/zsh/zshrc
ZSH_ALREADY_INSTALLED="true"
fi
# Adapted, simplified inline Oh My Zsh! install steps that adds, defaults to a codespaces theme.
# See https://github.com/ohmyzsh/ohmyzsh/blob/master/tools/install.sh for official script.
oh_my_install_dir="${user_rc_path}/.oh-my-zsh"
if [ ! -d "${oh_my_install_dir}" ] && [ "${INSTALL_OH_MY_ZSH}" = "true" ]; then
template_path="${oh_my_install_dir}/templates/zshrc.zsh-template"
user_rc_file="${user_rc_path}/.zshrc"
umask g-w,o-w
mkdir -p ${oh_my_install_dir}
git clone --depth=1 \
-c core.eol=lf \
-c core.autocrlf=false \
-c fsck.zeroPaddedFilemode=ignore \
-c fetch.fsck.zeroPaddedFilemode=ignore \
-c receive.fsck.zeroPaddedFilemode=ignore \
"https://github.com/ohmyzsh/ohmyzsh" "${oh_my_install_dir}" 2>&1
echo -e "$(cat "${template_path}")\nDISABLE_AUTO_UPDATE=true\nDISABLE_UPDATE_PROMPT=true" > ${user_rc_file}
sed -i -e 's/ZSH_THEME=.*/ZSH_THEME="codespaces"/g' ${user_rc_file}
mkdir -p ${oh_my_install_dir}/custom/themes
echo "${codespaces_zsh}" > "${oh_my_install_dir}/custom/themes/codespaces.zsh-theme"
# Shrink git while still enabling updates
cd "${oh_my_install_dir}"
git repack -a -d -f --depth=1 --window=1
# Copy to non-root user if one is specified
if [ "${USERNAME}" != "root" ]; then
cp -rf "${user_rc_file}" "${oh_my_install_dir}" /root
chown -R ${USERNAME}:${group_name} "${user_rc_path}"
fi
fi
fi
# Persist image metadata info, script if meta.env found in same directory
meta_info_script="$(cat << 'EOF'
#!/bin/sh
. /usr/local/etc/vscode-dev-containers/meta.env
# Minimal output
if [ "$1" = "version" ] || [ "$1" = "image-version" ]; then
echo "${VERSION}"
exit 0
elif [ "$1" = "release" ]; then
echo "${GIT_REPOSITORY_RELEASE}"
exit 0
elif [ "$1" = "content" ] || [ "$1" = "content-url" ] || [ "$1" = "contents" ] || [ "$1" = "contents-url" ]; then
echo "${CONTENTS_URL}"
exit 0
fi
#Full output
echo
echo "Development container image information"
echo
if [ ! -z "${VERSION}" ]; then echo "- Image version: ${VERSION}"; fi
if [ ! -z "${DEFINITION_ID}" ]; then echo "- Definition ID: ${DEFINITION_ID}"; fi
if [ ! -z "${VARIANT}" ]; then echo "- Variant: ${VARIANT}"; fi
if [ ! -z "${GIT_REPOSITORY}" ]; then echo "- Source code repository: ${GIT_REPOSITORY}"; fi
if [ ! -z "${GIT_REPOSITORY_RELEASE}" ]; then echo "- Source code release/branch: ${GIT_REPOSITORY_RELEASE}"; fi
if [ ! -z "${BUILD_TIMESTAMP}" ]; then echo "- Timestamp: ${BUILD_TIMESTAMP}"; fi
if [ ! -z "${CONTENTS_URL}" ]; then echo && echo "More info: ${CONTENTS_URL}"; fi
echo
EOF
)"
if [ -f "${DEV_CONTAINERS_DIR}/meta.env" ]; then
echo "${meta_info_script}" > /usr/local/bin/devcontainer-info
chmod +x /usr/local/bin/devcontainer-info
fi
if [ ! -d "${DEV_CONTAINERS_DIR}" ]; then
mkdir -p "$(dirname "${MARKER_FILE}")"
fi
# Write marker file
echo -e "\
PACKAGES_ALREADY_INSTALLED=${PACKAGES_ALREADY_INSTALLED}\n\
LOCALE_ALREADY_SET=${LOCALE_ALREADY_SET}\n\
EXISTING_NON_ROOT_USER=${EXISTING_NON_ROOT_USER}\n\
RC_SNIPPET_ALREADY_ADDED=${RC_SNIPPET_ALREADY_ADDED}\n\
ZSH_ALREADY_INSTALLED=${ZSH_ALREADY_INSTALLED}" > "${MARKER_FILE}"
echo "Done!"

573
src/common-utils/main.sh Normal file
View file

@ -0,0 +1,573 @@
#!/bin/bash
#-------------------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://github.com/devcontainers/features/blob/main/LICENSE for license information.
#-------------------------------------------------------------------------------------------------------------------------
#
# Docs: https://github.com/devcontainers/features/tree/main/src/common-utils
# Maintainer: The Dev Container spec maintainers
set -e
INSTALL_ZSH="${INSTALLZSH:-"true"}"
CONFIGURE_ZSH_AS_DEFAULT_SHELL="${CONFIGUREZSHASDEFAULTSHELL:-"false"}"
INSTALL_OH_MY_ZSH="${INSTALLOHMYZSH:-"true"}"
INSTALL_OH_MY_ZSH_CONFIG="${INSTALLOHMYZSHCONFIG:-"true"}"
UPGRADE_PACKAGES="${UPGRADEPACKAGES:-"true"}"
USERNAME="${USERNAME:-"automatic"}"
USER_UID="${USERUID:-"automatic"}"
USER_GID="${USERGID:-"automatic"}"
ADD_NON_FREE_PACKAGES="${NONFREEPACKAGES:-"false"}"
MARKER_FILE="/usr/local/etc/vscode-dev-containers/common"
FEATURE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# Debian / Ubuntu packages
install_debian_packages() {
# Ensure apt is in non-interactive to avoid prompts
export DEBIAN_FRONTEND=noninteractive
local package_list=""
if [ "${PACKAGES_ALREADY_INSTALLED}" != "true" ]; then
package_list="${package_list} \
apt-utils \
openssh-client \
gnupg2 \
dirmngr \
iproute2 \
procps \
lsof \
htop \
net-tools \
psmisc \
curl \
tree \
wget \
rsync \
ca-certificates \
unzip \
bzip2 \
zip \
nano \
vim-tiny \
less \
jq \
lsb-release \
apt-transport-https \
dialog \
libc6 \
libgcc1 \
libkrb5-3 \
libgssapi-krb5-2 \
libicu[0-9][0-9] \
liblttng-ust[0-9] \
libstdc++6 \
zlib1g \
locales \
sudo \
ncdu \
man-db \
strace \
manpages \
manpages-dev \
init-system-helpers"
# Include libssl1.1 if available
if [[ ! -z $(apt-cache --names-only search ^libssl1.1$) ]]; then
package_list="${package_list} libssl1.1"
fi
# Include libssl3 if available
if [[ ! -z $(apt-cache --names-only search ^libssl3$) ]]; then
package_list="${package_list} libssl3"
fi
# Include appropriate version of libssl1.0.x if available
local libssl_package=$(dpkg-query -f '${db:Status-Abbrev}\t${binary:Package}\n' -W 'libssl1\.0\.?' 2>&1 || echo '')
if [ "$(echo "$libssl_package" | grep -o 'libssl1\.0\.[0-9]:' | uniq | sort | wc -l)" -eq 0 ]; then
if [[ ! -z $(apt-cache --names-only search ^libssl1.0.2$) ]]; then
# Debian 9
package_list="${package_list} libssl1.0.2"
elif [[ ! -z $(apt-cache --names-only search ^libssl1.0.0$) ]]; then
# Ubuntu 18.04
package_list="${package_list} libssl1.0.0"
fi
fi
# Include git if not already installed (may be more recent than distro version)
if ! type git > /dev/null 2>&1; then
package_list="${package_list} git"
fi
fi
# Needed for adding manpages-posix and manpages-posix-dev which are non-free packages in Debian
if [ "${ADD_NON_FREE_PACKAGES}" = "true" ]; then
# Bring in variables from /etc/os-release like VERSION_CODENAME
sed -i -E "s/deb http:\/\/(deb|httpredir)\.debian\.org\/debian ${VERSION_CODENAME} main/deb http:\/\/\1\.debian\.org\/debian ${VERSION_CODENAME} main contrib non-free/" /etc/apt/sources.list
sed -i -E "s/deb-src http:\/\/(deb|httredir)\.debian\.org\/debian ${VERSION_CODENAME} main/deb http:\/\/\1\.debian\.org\/debian ${VERSION_CODENAME} main contrib non-free/" /etc/apt/sources.list
sed -i -E "s/deb http:\/\/(deb|httpredir)\.debian\.org\/debian ${VERSION_CODENAME}-updates main/deb http:\/\/\1\.debian\.org\/debian ${VERSION_CODENAME}-updates main contrib non-free/" /etc/apt/sources.list
sed -i -E "s/deb-src http:\/\/(deb|httpredir)\.debian\.org\/debian ${VERSION_CODENAME}-updates main/deb http:\/\/\1\.debian\.org\/debian ${VERSION_CODENAME}-updates main contrib non-free/" /etc/apt/sources.list
sed -i "s/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}\/updates main/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}\/updates main contrib non-free/" /etc/apt/sources.list
sed -i "s/deb-src http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}\/updates main/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}\/updates main contrib non-free/" /etc/apt/sources.list
sed -i "s/deb http:\/\/deb\.debian\.org\/debian ${VERSION_CODENAME}-backports main/deb http:\/\/deb\.debian\.org\/debian ${VERSION_CODENAME}-backports main contrib non-free/" /etc/apt/sources.list
sed -i "s/deb-src http:\/\/deb\.debian\.org\/debian ${VERSION_CODENAME}-backports main/deb http:\/\/deb\.debian\.org\/debian ${VERSION_CODENAME}-backports main contrib non-free/" /etc/apt/sources.list
# Handle bullseye location for security https://www.debian.org/releases/bullseye/amd64/release-notes/ch-information.en.html
sed -i "s/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}-security main/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}-security main contrib non-free/" /etc/apt/sources.list
sed -i "s/deb-src http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}-security main/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}-security main contrib non-free/" /etc/apt/sources.list
echo "Running apt-get update..."
package_list="${package_list} manpages-posix manpages-posix-dev"
fi
# Install the list of packages
echo "Packages to verify are installed: ${package_list}"
rm -rf /var/lib/apt/lists/*
apt-get update -y
apt-get -y install --no-install-recommends ${package_list} 2> >( grep -v 'debconf: delaying package configuration, since apt-utils is not installed' >&2 )
# Install zsh (and recommended packages) if needed
if [ "${INSTALL_ZSH}" = "true" ] && ! type zsh > /dev/null 2>&1; then
apt-get install -y zsh
fi
# Get to latest versions of all packages
if [ "${UPGRADE_PACKAGES}" = "true" ]; then
apt-get -y upgrade --no-install-recommends
apt-get autoremove -y
fi
# Ensure at least the en_US.UTF-8 UTF-8 locale is available = common need for both applications and things like the agnoster ZSH theme.
if [ "${LOCALE_ALREADY_SET}" != "true" ] && ! grep -o -E '^\s*en_US.UTF-8\s+UTF-8' /etc/locale.gen > /dev/null; then
echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen
locale-gen
LOCALE_ALREADY_SET="true"
fi
PACKAGES_ALREADY_INSTALLED="true"
# Clean up
apt-get -y clean
rm -rf /var/lib/apt/lists/*
}
# RedHat / RockyLinux / CentOS / Fedora packages
install_redhat_packages() {
local package_list=""
local remove_epel="false"
local install_cmd=dnf
if ! type dnf > /dev/null 2>&1; then
install_cmd=yum
fi
if [ "${PACKAGES_ALREADY_INSTALLED}" != "true" ]; then
package_list="${package_list} \
gawk \
openssh-clients \
gnupg2 \
iproute \
procps \
lsof \
net-tools \
psmisc \
wget \
ca-certificates \
rsync \
unzip \
zip \
nano \
vim-minimal \
less \
jq \
openssl-libs \
krb5-libs \
libicu \
zlib \
sudo \
sed \
grep \
which \
man-db \
strace"
# rockylinux:9 installs 'curl-minimal' which clashes with 'curl'
# Install 'curl' for every OS except this rockylinux:9
if [[ "${ID}" = "rocky" ]] && [[ "${VERSION}" != *"9."* ]]; then
package_list="${package_list} curl"
fi
# Install OpenSSL 1.0 compat if needed
if ${install_cmd} -q list compat-openssl10 >/dev/null 2>&1; then
package_list="${package_list} compat-openssl10"
fi
# Install lsb_release if available
if ${install_cmd} -q list redhat-lsb-core >/dev/null 2>&1; then
package_list="${package_list} redhat-lsb-core"
fi
# Install git if not already installed (may be more recent than distro version)
if ! type git > /dev/null 2>&1; then
package_list="${package_list} git"
fi
# Install EPEL repository if needed (required to install 'jq' for CentOS)
if ! ${install_cmd} -q list jq >/dev/null 2>&1; then
${install_cmd} -y install epel-release
remove_epel="true"
fi
fi
# Install zsh if needed
if [ "${INSTALL_ZSH}" = "true" ] && ! type zsh > /dev/null 2>&1; then
package_list="${package_list} zsh"
fi
if [ -n "${package_list}" ]; then
${install_cmd} -y install ${package_list}
fi
# Get to latest versions of all packages
if [ "${UPGRADE_PACKAGES}" = "true" ]; then
${install_cmd} upgrade -y
fi
if [[ "${remove_epel}" = "true" ]]; then
${install_cmd} -y remove epel-release
fi
PACKAGES_ALREADY_INSTALLED="true"
}
# Alpine Linux packages
install_alpine_packages() {
apk update
if [ "${PACKAGES_ALREADY_INSTALLED}" != "true" ]; then
apk add --no-cache \
openssh-client \
gnupg \
procps \
lsof \
htop \
net-tools \
psmisc \
curl \
wget \
rsync \
ca-certificates \
unzip \
zip \
nano \
vim \
less \
jq \
libgcc \
libstdc++ \
krb5-libs \
libintl \
libssl1.1 \
lttng-ust \
tzdata \
userspace-rcu \
zlib \
sudo \
coreutils \
sed \
grep \
which \
ncdu \
shadow \
strace
# Install man pages - package name varies between 3.12 and earlier versions
if apk info man > /dev/null 2>&1; then
apk add --no-cache man man-pages
else
apk add --no-cache mandoc man-pages
fi
# Install git if not already installed (may be more recent than distro version)
if ! type git > /dev/null 2>&1; then
apk add --no-cache git
fi
fi
# Install zsh if needed
if [ "${INSTALL_ZSH}" = "true" ] && ! type zsh > /dev/null 2>&1; then
apk add --no-cache zsh
fi
PACKAGES_ALREADY_INSTALLED="true"
}
# ******************
# ** Main section **
# ******************
if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi
# Load markers to see which steps have already run
if [ -f "${MARKER_FILE}" ]; then
echo "Marker file found:"
cat "${MARKER_FILE}"
source "${MARKER_FILE}"
fi
# Ensure that login shells get the correct path if the user updated the PATH using ENV.
rm -f /etc/profile.d/00-restore-env.sh
echo "export PATH=${PATH//$(sh -lc 'echo $PATH')/\$PATH}" > /etc/profile.d/00-restore-env.sh
chmod +x /etc/profile.d/00-restore-env.sh
# Bring in ID, ID_LIKE, VERSION_ID, VERSION_CODENAME
. /etc/os-release
# Get an adjusted ID independent of distro variants
if [ "${ID}" = "debian" ] || [ "${ID_LIKE}" = "debian" ]; then
ADJUSTED_ID="debian"
elif [[ "${ID}" = "rhel" || "${ID}" = "fedora" || "${ID}" = "mariner" || "${ID_LIKE}" = *"rhel"* || "${ID_LIKE}" = *"fedora"* || "${ID_LIKE}" = *"mariner"* ]]; then
ADJUSTED_ID="rhel"
elif [ "${ID}" = "alpine" ]; then
ADJUSTED_ID="alpine"
else
echo "Linux distro ${ID} not supported."
exit 1
fi
# Install packages for appropriate OS
case "${ADJUSTED_ID}" in
"debian")
install_debian_packages
;;
"rhel")
install_redhat_packages
;;
"alpine")
install_alpine_packages
;;
esac
# If in automatic mode, determine if a user already exists, if not use vscode
if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then
if [ "${_REMOTE_USER}" != "root" ]; then
USERNAME="${_REMOTE_USER}"
else
USERNAME=""
POSSIBLE_USERS=("devcontainer" "vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)")
for CURRENT_USER in "${POSSIBLE_USERS[@]}"; do
if id -u ${CURRENT_USER} > /dev/null 2>&1; then
USERNAME=${CURRENT_USER}
break
fi
done
if [ "${USERNAME}" = "" ]; then
USERNAME=vscode
fi
fi
elif [ "${USERNAME}" = "none" ]; then
USERNAME=root
USER_UID=0
USER_GID=0
fi
# Create or update a non-root user to match UID/GID.
group_name="${USERNAME}"
if id -u ${USERNAME} > /dev/null 2>&1; then
# User exists, update if needed
if [ "${USER_GID}" != "automatic" ] && [ "$USER_GID" != "$(id -g $USERNAME)" ]; then
group_name="$(id -gn $USERNAME)"
groupmod --gid $USER_GID ${group_name}
usermod --gid $USER_GID $USERNAME
fi
if [ "${USER_UID}" != "automatic" ] && [ "$USER_UID" != "$(id -u $USERNAME)" ]; then
usermod --uid $USER_UID $USERNAME
fi
else
# Create user
if [ "${USER_GID}" = "automatic" ]; then
groupadd $USERNAME
else
groupadd --gid $USER_GID $USERNAME
fi
if [ "${USER_UID}" = "automatic" ]; then
useradd -s /bin/bash --gid $USERNAME -m $USERNAME
else
useradd -s /bin/bash --uid $USER_UID --gid $USERNAME -m $USERNAME
fi
fi
# Add add sudo support for non-root user
if [ "${USERNAME}" != "root" ] && [ "${EXISTING_NON_ROOT_USER}" != "${USERNAME}" ]; then
echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME
chmod 0440 /etc/sudoers.d/$USERNAME
EXISTING_NON_ROOT_USER="${USERNAME}"
fi
# *********************************
# ** Shell customization section **
# *********************************
if [ "${USERNAME}" = "root" ]; then
user_home="/root"
# Check if user already has a home directory other than /home/${USERNAME}
elif [ "/home/${USERNAME}" != $( getent passwd $USERNAME | cut -d: -f6 ) ]; then
user_home=$( getent passwd $USERNAME | cut -d: -f6 )
else
user_home="/home/${USERNAME}"
if [ ! -d "${user_home}" ]; then
mkdir -p "${user_home}"
chown ${USERNAME}:${group_name} "${user_home}"
fi
fi
# Restore user .bashrc / .profile / .zshrc defaults from skeleton file if it doesn't exist or is empty
possible_rc_files=( ".bashrc" ".profile" )
[ "$INSTALL_OH_MY_ZSH_CONFIG" == "true" ] && possible_rc_files+=('.zshrc')
[ "$INSTALL_ZSH" == "true" ] && possible_rc_files+=('.zprofile')
for rc_file in "${possible_rc_files[@]}"; do
if [ -f "/etc/skel/${rc_file}" ]; then
if [ ! -e "${user_home}/${rc_file}" ] || [ ! -s "${user_home}/${rc_file}" ]; then
cp "/etc/skel/${rc_file}" "${user_home}/${rc_file}"
chown ${USERNAME}:${group_name} "${user_home}/${rc_file}"
fi
fi
done
# Add RC snippet and custom bash prompt
if [ "${RC_SNIPPET_ALREADY_ADDED}" != "true" ]; then
case "${ADJUSTED_ID}" in
"debian")
global_rc_path="/etc/bash.bashrc"
;;
"rhel")
global_rc_path="/etc/bashrc"
;;
"alpine")
global_rc_path="/etc/bash/bashrc"
# /etc/bash/bashrc does not exist in alpine 3.14 & 3.15
mkdir -p /etc/bash
;;
esac
cat "${FEATURE_DIR}/scripts/rc_snippet.sh" >> ${global_rc_path}
cat "${FEATURE_DIR}/scripts/bash_theme_snippet.sh" >> "${user_home}/.bashrc"
if [ "${USERNAME}" != "root" ]; then
cat "${FEATURE_DIR}/scripts/bash_theme_snippet.sh" >> "/root/.bashrc"
chown ${USERNAME}:${group_name} "${user_home}/.bashrc"
fi
RC_SNIPPET_ALREADY_ADDED="true"
fi
# Optionally configure zsh and Oh My Zsh!
if [ "${INSTALL_ZSH}" = "true" ]; then
if [ ! -f "${user_home}/.zprofile" ]; then
touch "${user_home}/.zprofile"
echo 'source $HOME/.profile' >> "${user_home}/.zprofile" # TODO: Reconsider adding '.profile' to '.zprofile'
chown ${USERNAME}:${group_name} "${user_home}/.zprofile"
fi
if [ "${ZSH_ALREADY_INSTALLED}" != "true" ]; then
if [ "${ADJUSTED_ID}" = "rhel" ]; then
global_rc_path="/etc/zshrc"
else
global_rc_path="/etc/zsh/zshrc"
fi
cat "${FEATURE_DIR}/scripts/rc_snippet.sh" >> ${global_rc_path}
ZSH_ALREADY_INSTALLED="true"
fi
if [ "${CONFIGURE_ZSH_AS_DEFAULT_SHELL}" == "true" ]; then
# Fixing chsh always asking for a password on alpine linux
# ref: https://askubuntu.com/questions/812420/chsh-always-asking-a-password-and-get-pam-authentication-failure.
if [ ! -f "/etc/pam.d/chsh" ] || ! grep -Eq '^auth(.*)pam_rootok\.so$' /etc/pam.d/chsh; then
echo "auth sufficient pam_rootok.so" >> /etc/pam.d/chsh
elif [[ -n "$(awk '/^auth(.*)pam_rootok\.so$/ && !/^auth[[:blank:]]+sufficient[[:blank:]]+pam_rootok\.so$/' /etc/pam.d/chsh)" ]]; then
awk '/^auth(.*)pam_rootok\.so$/ { $2 = "sufficient" } { print }' /etc/pam.d/chsh > /tmp/chsh.tmp && mv /tmp/chsh.tmp /etc/pam.d/chsh
fi
chsh --shell /bin/zsh ${USERNAME}
fi
# Adapted, simplified inline Oh My Zsh! install steps that adds, defaults to a codespaces theme.
# See https://github.com/ohmyzsh/ohmyzsh/blob/master/tools/install.sh for official script.
if [ "${INSTALL_OH_MY_ZSH}" = "true" ]; then
user_rc_file="${user_home}/.zshrc"
oh_my_install_dir="${user_home}/.oh-my-zsh"
template_path="${oh_my_install_dir}/templates/zshrc.zsh-template"
if [ ! -d "${oh_my_install_dir}" ]; then
umask g-w,o-w
mkdir -p ${oh_my_install_dir}
git clone --depth=1 \
-c core.eol=lf \
-c core.autocrlf=false \
-c fsck.zeroPaddedFilemode=ignore \
-c fetch.fsck.zeroPaddedFilemode=ignore \
-c receive.fsck.zeroPaddedFilemode=ignore \
"https://github.com/ohmyzsh/ohmyzsh" "${oh_my_install_dir}" 2>&1
# Shrink git while still enabling updates
cd "${oh_my_install_dir}"
git repack -a -d -f --depth=1 --window=1
fi
# Add Dev Containers theme
mkdir -p ${oh_my_install_dir}/custom/themes
cp -f "${FEATURE_DIR}/scripts/devcontainers.zsh-theme" "${oh_my_install_dir}/custom/themes/devcontainers.zsh-theme"
ln -sf "${oh_my_install_dir}/custom/themes/devcontainers.zsh-theme" "${oh_my_install_dir}/custom/themes/codespaces.zsh-theme"
# Add devcontainer .zshrc template
if [ "$INSTALL_OH_MY_ZSH_CONFIG" = "true" ]; then
echo -e "$(cat "${template_path}")\nDISABLE_AUTO_UPDATE=true\nDISABLE_UPDATE_PROMPT=true" > ${user_rc_file}
sed -i -e 's/ZSH_THEME=.*/ZSH_THEME="devcontainers"/g' ${user_rc_file}
fi
# Copy to non-root user if one is specified
if [ "${USERNAME}" != "root" ]; then
copy_to_user_files=("${oh_my_install_dir}")
[ -f "$user_rc_file" ] && copy_to_user_files+=("$user_rc_file")
cp -rf "${copy_to_user_files[@]}" /root
chown -R ${USERNAME}:${group_name} "${copy_to_user_files[@]}"
fi
fi
fi
# *********************************
# ** Ensure config directory **
# *********************************
user_config_dir="${user_home}/.config"
if [ ! -d "${user_config_dir}" ]; then
mkdir -p "${user_config_dir}"
chown ${USERNAME}:${group_name} "${user_config_dir}"
fi
# ****************************
# ** Utilities and commands **
# ****************************
# code shim, it fallbacks to code-insiders if code is not available
cp -f "${FEATURE_DIR}/bin/code" /usr/local/bin/
chmod +rx /usr/local/bin/code
# systemctl shim for Debian/Ubuntu - tells people to use 'service' if systemd is not running
if [ "${ADJUSTED_ID}" = "debian" ]; then
cp -f "${FEATURE_DIR}/bin/systemctl" /usr/local/bin/systemctl
chmod +rx /usr/local/bin/systemctl
fi
# Persist image metadata info, script if meta.env found in same directory
if [ -f "/usr/local/etc/vscode-dev-containers/meta.env" ] || [ -f "/usr/local/etc/dev-containers/meta.env" ]; then
cp -f "${FEATURE_DIR}/bin/devcontainer-info" /usr/local/bin/devcontainer-info
chmod +rx /usr/local/bin/devcontainer-info
fi
# Write marker file
if [ ! -d "/usr/local/etc/vscode-dev-containers" ]; then
mkdir -p "$(dirname "${MARKER_FILE}")"
fi
echo -e "\
PACKAGES_ALREADY_INSTALLED=${PACKAGES_ALREADY_INSTALLED}\n\
LOCALE_ALREADY_SET=${LOCALE_ALREADY_SET}\n\
EXISTING_NON_ROOT_USER=${EXISTING_NON_ROOT_USER}\n\
RC_SNIPPET_ALREADY_ADDED=${RC_SNIPPET_ALREADY_ADDED}\n\
ZSH_ALREADY_INSTALLED=${ZSH_ALREADY_INSTALLED}" > "${MARKER_FILE}"
echo "Done!"

View file

@ -0,0 +1,25 @@
# bash theme - partly inspired by https://github.com/ohmyzsh/ohmyzsh/blob/master/themes/robbyrussell.zsh-theme
__bash_prompt() {
local userpart='`export XIT=$? \
&& [ ! -z "${GITHUB_USER}" ] && echo -n "\[\033[0;32m\]@${GITHUB_USER} " || echo -n "\[\033[0;32m\]\u " \
&& [ "$XIT" -ne "0" ] && echo -n "\[\033[1;31m\]➜" || echo -n "\[\033[0m\]➜"`'
local gitbranch='`\
if [ "$(git config --get devcontainers-theme.hide-status 2>/dev/null)" != 1 ] && [ "$(git config --get codespaces-theme.hide-status 2>/dev/null)" != 1 ]; then \
export BRANCH=$(git --no-optional-locks symbolic-ref --short HEAD 2>/dev/null || git --no-optional-locks rev-parse --short HEAD 2>/dev/null); \
if [ "${BRANCH}" != "" ]; then \
echo -n "\[\033[0;36m\](\[\033[1;31m\]${BRANCH}" \
&& if [ "$(git config --get devcontainers-theme.show-dirty 2>/dev/null)" = 1 ] && \
git --no-optional-locks ls-files --error-unmatch -m --directory --no-empty-directory -o --exclude-standard ":/*" > /dev/null 2>&1; then \
echo -n " \[\033[1;33m\]✗"; \
fi \
&& echo -n "\[\033[0;36m\]) "; \
fi; \
fi`'
local lightblue='\[\033[1;34m\]'
local removecolor='\[\033[0m\]'
PS1="${userpart} ${lightblue}\w ${gitbranch}${removecolor}\$ "
unset -f __bash_prompt
}
__bash_prompt
export PROMPT_DIRTRIM=4

View file

@ -0,0 +1,26 @@
# Oh My Zsh! theme - partly inspired by https://github.com/ohmyzsh/ohmyzsh/blob/master/themes/robbyrussell.zsh-theme
__zsh_prompt() {
local prompt_username
if [ ! -z "${GITHUB_USER}" ]; then
prompt_username="@${GITHUB_USER}"
else
prompt_username="%n"
fi
PROMPT="%{$fg[green]%}${prompt_username} %(?:%{$reset_color%}➜ :%{$fg_bold[red]%}➜ )" # User/exit code arrow
PROMPT+='%{$fg_bold[blue]%}%(5~|%-1~/…/%3~|%4~)%{$reset_color%} ' # cwd
PROMPT+='`\
if [ "$(git config --get devcontainers-theme.hide-status 2>/dev/null)" != 1 ] && [ "$(git config --get codespaces-theme.hide-status 2>/dev/null)" != 1 ]; then \
export BRANCH=$(git --no-optional-locks symbolic-ref --short HEAD 2>/dev/null || git --no-optional-locks rev-parse --short HEAD 2>/dev/null); \
if [ "${BRANCH}" != "" ]; then \
echo -n "%{$fg_bold[cyan]%}(%{$fg_bold[red]%}${BRANCH}" \
&& if [ "$(git config --get devcontainers-theme.show-dirty 2>/dev/null)" = 1 ] && \
git --no-optional-locks ls-files --error-unmatch -m --directory --no-empty-directory -o --exclude-standard ":/*" > /dev/null 2>&1; then \
echo -n " %{$fg_bold[yellow]%}✗"; \
fi \
&& echo -n "%{$fg_bold[cyan]%})%{$reset_color%} "; \
fi; \
fi`'
PROMPT+='%{$fg[white]%}$ %{$reset_color%}'
unset -f __zsh_prompt
}
__zsh_prompt

View file

@ -0,0 +1,26 @@
if [ -z "${USER}" ]; then export USER=$(whoami); fi
if [[ "${PATH}" != *"$HOME/.local/bin"* ]]; then export PATH="${PATH}:$HOME/.local/bin"; fi
# Display optional first run image specific notice if configured and terminal is interactive
if [ -t 1 ] && [[ "${TERM_PROGRAM}" = "vscode" || "${TERM_PROGRAM}" = "codespaces" ]] && [ ! -f "$HOME/.config/vscode-dev-containers/first-run-notice-already-displayed" ]; then
if [ -f "/usr/local/etc/vscode-dev-containers/first-run-notice.txt" ]; then
cat "/usr/local/etc/vscode-dev-containers/first-run-notice.txt"
elif [ -f "/workspaces/.codespaces/shared/first-run-notice.txt" ]; then
cat "/workspaces/.codespaces/shared/first-run-notice.txt"
fi
mkdir -p "$HOME/.config/vscode-dev-containers"
# Mark first run notice as displayed after 10s to avoid problems with fast terminal refreshes hiding it
((sleep 10s; touch "$HOME/.config/vscode-dev-containers/first-run-notice-already-displayed") &)
fi
# Set the default git editor if not already set
if [ -z "$(git config --get core.editor)" ] && [ -z "${GIT_EDITOR}" ]; then
if [ "${TERM_PROGRAM}" = "vscode" ]; then
if [[ -n $(command -v code-insiders) && -z $(command -v code) ]]; then
export GIT_EDITOR="code-insiders --wait"
else
export GIT_EDITOR="code --wait"
fi
fi
fi

View file

@ -11,3 +11,10 @@ As covered in the [user FAQ](https://docs.anaconda.com/anaconda/user-guide/faq)
```bash ```bash
conda install python=3.7 conda install python=3.7
``` ```
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.

View file

@ -1,15 +1,13 @@
# Conda - A cross-platform, language-agnostic binary package manager (conda) # Conda (conda)
A cross-platform, language-agnostic binary package manager
## Example Usage ## Example Usage
```json ```json
"features": { "features": {
"ghcr.io/devcontainers/features/conda:1": { "ghcr.io/devcontainers/features/conda:1": {}
"version": "latest"
}
} }
``` ```
@ -18,7 +16,7 @@
| Options Id | Description | Type | Default Value | | Options Id | Description | Type | Default Value |
|-----|-----|-----|-----| |-----|-----|-----|-----|
| version | Select or enter a conda version. | string | latest | | version | Select or enter a conda version. | string | latest |
| addCondaForge | Add conda-forge channel to the config? | boolean | - | | addCondaForge | Add conda-forge channel to the config? | boolean | false |
## Using Conda ## Using Conda
@ -35,6 +33,13 @@ conda install python=3.7
``` ```
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.
--- ---
_Note: This file was auto-generated from the [devcontainer-feature.json](https://github.com/devcontainers/features/blob/main/src/conda/devcontainer-feature.json). Add additional notes to a `NOTES.md`._ _Note: This file was auto-generated from the [devcontainer-feature.json](https://github.com/devcontainers/features/blob/main/src/conda/devcontainer-feature.json). Add additional notes to a `NOTES.md`._

View file

@ -1,7 +1,8 @@
{ {
"id": "conda", "id": "conda",
"version": "1.0.2", "version": "1.0.9",
"name": "Conda - A cross-platform, language-agnostic binary package manager", "name": "Conda",
"description": "A cross-platform, language-agnostic binary package manager",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/conda", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/conda",
"options": { "options": {
"version": { "version": {
@ -24,5 +25,8 @@
"CONDA_DIR": "/opt/conda", "CONDA_DIR": "/opt/conda",
"CONDA_SCRIPT":"/opt/conda/etc/profile.d/conda.sh", "CONDA_SCRIPT":"/opt/conda/etc/profile.d/conda.sh",
"PATH": "/opt/conda/bin:${PATH}" "PATH": "/opt/conda/bin:${PATH}"
} },
"installsAfter": [
"ghcr.io/devcontainers/features/common-utils"
]
} }

View file

@ -7,13 +7,16 @@
VERSION=${VERSION:-"latest"} VERSION=${VERSION:-"latest"}
ADD_CONDA_FORGE=$ADDCONDAFORGE ADD_CONDA_FORGE=$ADDCONDAFORGE
USERNAME="automatic" USERNAME="${USERNAME:-"${_REMOTE_USER:-"automatic"}"}"
UPDATE_RC="true" UPDATE_RC="true"
CONDA_DIR="/opt/conda" CONDA_DIR="/opt/conda"
set -eux set -eux
export DEBIAN_FRONTEND=noninteractive export DEBIAN_FRONTEND=noninteractive
# Clean up
rm -rf /var/lib/apt/lists/*
if [ "$(id -u)" -ne 0 ]; then if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1 exit 1
@ -50,15 +53,28 @@ fi
# Checks if packages are installed and installs them if not # Checks if packages are installed and installs them if not
check_packages() { check_packages() {
if ! dpkg -s "$@" > /dev/null 2>&1; then if ! dpkg -s "$@" > /dev/null 2>&1; then
apt-get update -y if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then
echo "Running apt-get update..."
apt-get update -y
fi
apt-get -y install --no-install-recommends "$@" apt-get -y install --no-install-recommends "$@"
# Clean up
apt-get clean -y
rm -rf /var/lib/apt/lists/*
fi fi
} }
sudo_if() {
COMMAND="$*"
if [ "$(id -u)" -eq 0 ] && [ "$USERNAME" != "root" ]; then
su - "$USERNAME" -c "$COMMAND"
else
$COMMAND
fi
}
install_user_package() {
PACKAGE="$1"
sudo_if "${CONDA_DIR}/bin/python3" -m pip install --user --upgrade "$PACKAGE"
}
# Install Conda if it's missing # Install Conda if it's missing
if ! conda --version &> /dev/null ; then if ! conda --version &> /dev/null ; then
if ! cat /etc/group | grep -e "^conda:" > /dev/null 2>&1; then if ! cat /etc/group | grep -e "^conda:" > /dev/null 2>&1; then
@ -73,6 +89,7 @@ if ! conda --version &> /dev/null ; then
curl -sS https://repo.anaconda.com/pkgs/misc/gpgkeys/anaconda.asc | gpg --dearmor > /usr/share/keyrings/conda-archive-keyring.gpg curl -sS https://repo.anaconda.com/pkgs/misc/gpgkeys/anaconda.asc | gpg --dearmor > /usr/share/keyrings/conda-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/conda-archive-keyring.gpg] https://repo.anaconda.com/pkgs/misc/debrepo/conda stable main" > /etc/apt/sources.list.d/conda.list echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/conda-archive-keyring.gpg] https://repo.anaconda.com/pkgs/misc/debrepo/conda stable main" > /etc/apt/sources.list.d/conda.list
apt-get update -y
CONDA_PKG="conda=${VERSION}-0" CONDA_PKG="conda=${VERSION}-0"
if [ "${VERSION}" = "latest" ]; then if [ "${VERSION}" = "latest" ]; then
@ -96,6 +113,14 @@ if ! conda --version &> /dev/null ; then
chmod -R g+r+w "${CONDA_DIR}" chmod -R g+r+w "${CONDA_DIR}"
find "${CONDA_DIR}" -type d -print0 | xargs -n 1 -0 chmod g+s find "${CONDA_DIR}" -type d -print0 | xargs -n 1 -0 chmod g+s
# Temporary fixes
# Due to https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23491
install_user_package certifi
# Due to https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-0286 and https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-23931
install_user_package cryptography
# Due to https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-40897
install_user_package setuptools
fi fi
# Display a notice on conda when not running in GitHub Codespaces # Display a notice on conda when not running in GitHub Codespaces
@ -123,4 +148,7 @@ if [ -f "/etc/bash.bashrc" ]; then
echo "${notice_script}" | tee -a /etc/bash.bashrc echo "${notice_script}" | tee -a /etc/bash.bashrc
fi fi
# Clean up
rm -rf /var/lib/apt/lists/*
echo "Done!" echo "Done!"

View file

@ -6,6 +6,16 @@ This feature provides two ways of connecting to the desktop environment it adds.
1. Open the ports view in your tool, select the noVNC port, and click the Globe icon. 1. Open the ports view in your tool, select the noVNC port, and click the Globe icon.
1. In the browser that appears, click the **Connect** button and enter the desktop password (`vscode` by default). 1. In the browser that appears, click the **Connect** button and enter the desktop password (`vscode` by default).
To set up the `6080` port from your `devcontainer.json` file, include the following:
```json
"forwardPorts": [6080],
"portsAttributes": {
"6080": {
"label": "desktop"
}
}
```
You can also connect to the desktop using a [VNC viewer](https://www.realvnc.com/en/connect/download/viewer/). To do so: You can also connect to the desktop using a [VNC viewer](https://www.realvnc.com/en/connect/download/viewer/). To do so:
1. Connect to the environment from a desktop tool that supports the dev container spec (e.g., VS Code client). 1. Connect to the environment from a desktop tool that supports the dev container spec (e.g., VS Code client).
@ -15,7 +25,7 @@ You can also connect to the desktop using a [VNC viewer](https://www.realvnc.com
## Customizing Fluxbox ## Customizing Fluxbox
The window manager is installed is [Fluxbox](http://fluxbox.org/). **Right-click** to see the application menu. In addition, any UI-based commands you execute inside the dev container will automatically appear on the desktop. The window manager installed is [Fluxbox](http://fluxbox.org/). **Right-click** to see the application menu. In addition, any UI-based commands you execute inside the dev container will automatically appear on the desktop.
You can customize the desktop using Fluxbox configuration files. The configuration files are located in the `.fluxbox` folder of the home directory of the user you using to connect to the dev container (`$HOME/.fluxbox`). You can customize the desktop using Fluxbox configuration files. The configuration files are located in the `.fluxbox` folder of the home directory of the user you using to connect to the dev container (`$HOME/.fluxbox`).
@ -27,19 +37,19 @@ See the [Fluxbox menu documentation](http://www.fluxbox.org/help/man-fluxbox-men
If you run into applications crashing, you may need to increase the size of the shared memory space allocated to your container. For example, this will bump it up to 1 GB in `devcontainer.json`: If you run into applications crashing, you may need to increase the size of the shared memory space allocated to your container. For example, this will bump it up to 1 GB in `devcontainer.json`:
```json ```json
"runArgs": ["--shm-size=1g"] "runArgs": ["--shm-size=1g"]
``` ```
Or using Docker Compose: Or using Docker Compose:
```yaml ```yaml
services: services:
your-service-here: your-service-here:
# ... # ...
shm_size: '1gb' shm_size: '1gb'
# ... # ...
``` ```
## Installing a browser ## Installing a browser
@ -62,3 +72,10 @@ If you want the full version of **Google Chrome** in the desktop:
2. Chrome sandbox support requires you set up and run as a non-root user. The [`common-utils`](https://github.com/devcontainers/features/tree/main/src/common-utils) script can do this for you, or you [set one up yourself](https://aka.ms/vscode-remote/containers/non-root). Alternatively, you can start Chrome using `google-chrome --no-sandbox` 2. Chrome sandbox support requires you set up and run as a non-root user. The [`common-utils`](https://github.com/devcontainers/features/tree/main/src/common-utils) script can do this for you, or you [set one up yourself](https://aka.ms/vscode-remote/containers/non-root). Alternatively, you can start Chrome using `google-chrome --no-sandbox`
That's it! That's it!
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.

View file

@ -7,9 +7,7 @@ Adds a lightweight Fluxbox based desktop to the container that can be accessed u
```json ```json
"features": { "features": {
"ghcr.io/devcontainers/features/desktop-lite:1": { "ghcr.io/devcontainers/features/desktop-lite:1": {}
"version": "latest"
}
} }
``` ```
@ -31,6 +29,16 @@ This feature provides two ways of connecting to the desktop environment it adds.
1. Open the ports view in your tool, select the noVNC port, and click the Globe icon. 1. Open the ports view in your tool, select the noVNC port, and click the Globe icon.
1. In the browser that appears, click the **Connect** button and enter the desktop password (`vscode` by default). 1. In the browser that appears, click the **Connect** button and enter the desktop password (`vscode` by default).
To set up the `6080` port from your `devcontainer.json` file, include the following:
```json
"forwardPorts": [6080],
"portsAttributes": {
"6080": {
"label": "desktop"
}
}
```
You can also connect to the desktop using a [VNC viewer](https://www.realvnc.com/en/connect/download/viewer/). To do so: You can also connect to the desktop using a [VNC viewer](https://www.realvnc.com/en/connect/download/viewer/). To do so:
1. Connect to the environment from a desktop tool that supports the dev container spec (e.g., VS Code client). 1. Connect to the environment from a desktop tool that supports the dev container spec (e.g., VS Code client).
@ -40,7 +48,7 @@ You can also connect to the desktop using a [VNC viewer](https://www.realvnc.com
## Customizing Fluxbox ## Customizing Fluxbox
The window manager is installed is [Fluxbox](http://fluxbox.org/). **Right-click** to see the application menu. In addition, any UI-based commands you execute inside the dev container will automatically appear on the desktop. The window manager installed is [Fluxbox](http://fluxbox.org/). **Right-click** to see the application menu. In addition, any UI-based commands you execute inside the dev container will automatically appear on the desktop.
You can customize the desktop using Fluxbox configuration files. The configuration files are located in the `.fluxbox` folder of the home directory of the user you using to connect to the dev container (`$HOME/.fluxbox`). You can customize the desktop using Fluxbox configuration files. The configuration files are located in the `.fluxbox` folder of the home directory of the user you using to connect to the dev container (`$HOME/.fluxbox`).
@ -52,19 +60,19 @@ See the [Fluxbox menu documentation](http://www.fluxbox.org/help/man-fluxbox-men
If you run into applications crashing, you may need to increase the size of the shared memory space allocated to your container. For example, this will bump it up to 1 GB in `devcontainer.json`: If you run into applications crashing, you may need to increase the size of the shared memory space allocated to your container. For example, this will bump it up to 1 GB in `devcontainer.json`:
```json ```json
"runArgs": ["--shm-size=1g"] "runArgs": ["--shm-size=1g"]
``` ```
Or using Docker Compose: Or using Docker Compose:
```yaml ```yaml
services: services:
your-service-here: your-service-here:
# ... # ...
shm_size: '1gb' shm_size: '1gb'
# ... # ...
``` ```
## Installing a browser ## Installing a browser
@ -89,6 +97,13 @@ If you want the full version of **Google Chrome** in the desktop:
That's it! That's it!
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.
--- ---
_Note: This file was auto-generated from the [devcontainer-feature.json](https://github.com/devcontainers/features/blob/main/src/desktop-lite/devcontainer-feature.json). Add additional notes to a `NOTES.md`._ _Note: This file was auto-generated from the [devcontainer-feature.json](https://github.com/devcontainers/features/blob/main/src/desktop-lite/devcontainer-feature.json). Add additional notes to a `NOTES.md`._

View file

@ -1,6 +1,6 @@
{ {
"id": "desktop-lite", "id": "desktop-lite",
"version": "1.0.3", "version": "1.0.8",
"name": "Light-weight Desktop", "name": "Light-weight Desktop",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/desktop-lite", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/desktop-lite",
"description": "Adds a lightweight Fluxbox based desktop to the container that can be accessed using a VNC viewer or the web. GUI-based commands executed from the built-in VS code terminal will open on the desktop automatically.", "description": "Adds a lightweight Fluxbox based desktop to the container that can be accessed using a VNC viewer or the web. GUI-based commands executed from the built-in VS code terminal will open on the desktop automatically.",
@ -52,5 +52,8 @@
"entrypoint": "/usr/local/share/desktop-init.sh", "entrypoint": "/usr/local/share/desktop-init.sh",
"containerEnv": { "containerEnv": {
"DISPLAY": ":1" "DISPLAY": ":1"
} },
"installsAfter": [
"ghcr.io/devcontainers/features/common-utils"
]
} }

View file

@ -7,14 +7,13 @@
# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/desktop-lite.md # Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/desktop-lite.md
# Maintainer: The VS Code and Codespaces Teams # Maintainer: The VS Code and Codespaces Teams
NOVNC_VERSION=${NOVNCVERSION:-"1.2.0"} # TODO: Add in a 'latest' auto-detect and swap name to 'version' NOVNC_VERSION="${NOVNCVERSION:-"1.2.0"}" # TODO: Add in a 'latest' auto-detect and swap name to 'version'
VNC_PASSWORD=${PASSWORD:-"vscode"} VNC_PASSWORD=${PASSWORD:-"vscode"}
NOVNC_PORT="${WEBPORT:-6080}" NOVNC_PORT="${WEBPORT:-6080}"
VNC_PORT="${VNCPORT:-5901}" VNC_PORT="${VNCPORT:-5901}"
INSTALL_NOVNC=${INSTALL_NOVNC:-"true"} INSTALL_NOVNC="${INSTALL_NOVNC:-"true"}"
USERNAME=${USERNAME:-"automatic"} USERNAME="${USERNAME:-"${_REMOTE_USER:-"automatic"}"}"
WEBSOCKETIFY_VERSION=0.10.0 WEBSOCKETIFY_VERSION=0.10.0
@ -63,6 +62,9 @@ package_list_additional="
set -e set -e
# Clean up
rm -rf /var/lib/apt/lists/*
if [ "$(id -u)" -ne 0 ]; then if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1 exit 1
@ -151,8 +153,10 @@ copy_fluxbox_config() {
apt_get_update() apt_get_update()
{ {
echo "Running apt-get update..." if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then
apt-get update -y echo "Running apt-get update..."
apt-get update -y
fi
} }
# Checks if packages are installed and installs them if not # Checks if packages are installed and installs them if not
@ -172,11 +176,11 @@ export DEBIAN_FRONTEND=noninteractive
apt_get_update apt_get_update
# On older Ubuntu, Tilix is in a PPA. on Debian strech its in backports. # On older Ubuntu, Tilix is in a PPA. on Debian stretch its in backports.
if [[ -z $(apt-cache --names-only search ^tilix$) ]]; then if [[ -z $(apt-cache --names-only search ^tilix$) ]]; then
. /etc/os-release . /etc/os-release
if [ "${ID}" = "ubuntu" ]; then if [ "${ID}" = "ubuntu" ]; then
apt-get install -y --no-install-recommends apt-transport-https software-properties-common check_packages apt-transport-https software-properties-common
add-apt-repository -y ppa:webupd8team/terminix add-apt-repository -y ppa:webupd8team/terminix
elif [ "${VERSION_CODENAME}" = "stretch" ]; then elif [ "${VERSION_CODENAME}" = "stretch" ]; then
echo "deb http://deb.debian.org/debian stretch-backports main" > /etc/apt/sources.list.d/stretch-backports.list echo "deb http://deb.debian.org/debian stretch-backports main" > /etc/apt/sources.list.d/stretch-backports.list
@ -232,9 +236,7 @@ if [ "${INSTALL_NOVNC}" = "true" ] && [ ! -d "/usr/local/novnc" ]; then
rm -f /tmp/websockify-install.zip /tmp/novnc-install.zip rm -f /tmp/websockify-install.zip /tmp/novnc-install.zip
# Install noVNC dependencies and use them. # Install noVNC dependencies and use them.
if ! dpkg -s python3-minimal python3-numpy > /dev/null 2>&1; then check_packages python3-minimal python3-numpy
apt-get -y install --no-install-recommends python3-minimal python3-numpy
fi
sed -i -E 's/^python /python3 /' /usr/local/novnc/websockify-${WEBSOCKETIFY_VERSION}/run sed -i -E 's/^python /python3 /' /usr/local/novnc/websockify-${WEBSOCKETIFY_VERSION}/run
fi fi
@ -297,9 +299,9 @@ startInBackgroundIfNotRunning()
{ {
log "Starting \$1." log "Starting \$1."
echo -e "\n** \$(date) **" | sudoIf tee -a /tmp/\$1.log > /dev/null echo -e "\n** \$(date) **" | sudoIf tee -a /tmp/\$1.log > /dev/null
if ! pidof \$1 > /dev/null; then if ! pgrep -x \$1 > /dev/null; then
keepRunningInBackground "\$@" keepRunningInBackground "\$@"
while ! pidof \$1 > /dev/null; do while ! pgrep -x \$1 > /dev/null; do
sleep 1 sleep 1
done done
log "\$1 started." log "\$1 started."
@ -345,16 +347,16 @@ log "** SCRIPT START **"
# Start dbus. # Start dbus.
log 'Running "/etc/init.d/dbus start".' log 'Running "/etc/init.d/dbus start".'
if [ -f "/var/run/dbus/pid" ] && ! pidof dbus-daemon > /dev/null; then if [ -f "/var/run/dbus/pid" ] && ! pgrep -x dbus-daemon > /dev/null; then
sudoIf rm -f /var/run/dbus/pid sudoIf rm -f /var/run/dbus/pid
fi fi
sudoIf /etc/init.d/dbus start 2>&1 | sudoIf tee -a /tmp/dbus-daemon-system.log > /dev/null sudoIf /etc/init.d/dbus start 2>&1 | sudoIf tee -a /tmp/dbus-daemon-system.log > /dev/null
while ! pidof dbus-daemon > /dev/null; do while ! pgrep -x dbus-daemon > /dev/null; do
sleep 1 sleep 1
done done
# Startup tigervnc server and fluxbox # Startup tigervnc server and fluxbox
sudo rm -rf /tmp/.X11-unix /tmp/.X*-lock sudoIf rm -rf /tmp/.X11-unix /tmp/.X*-lock
mkdir -p /tmp/.X11-unix mkdir -p /tmp/.X11-unix
sudoIf chmod 1777 /tmp/.X11-unix sudoIf chmod 1777 /tmp/.X11-unix
sudoIf chown root:\${group_name} /tmp/.X11-unix sudoIf chown root:\${group_name} /tmp/.X11-unix
@ -363,7 +365,7 @@ screen_geometry="\${VNC_RESOLUTION%*x*}"
screen_depth="\${VNC_RESOLUTION##*x}" screen_depth="\${VNC_RESOLUTION##*x}"
startInBackgroundIfNotRunning "Xtigervnc" sudoUserIf "tigervncserver \${DISPLAY} -geometry \${screen_geometry} -depth \${screen_depth} -rfbport ${VNC_PORT} -dpi \${VNC_DPI:-96} -localhost -desktop fluxbox -fg -passwd /usr/local/etc/vscode-dev-containers/vnc-passwd" startInBackgroundIfNotRunning "Xtigervnc" sudoUserIf "tigervncserver \${DISPLAY} -geometry \${screen_geometry} -depth \${screen_depth} -rfbport ${VNC_PORT} -dpi \${VNC_DPI:-96} -localhost -desktop fluxbox -fg -passwd /usr/local/etc/vscode-dev-containers/vnc-passwd"
# Spin up noVNC if installed and not runnning. # Spin up noVNC if installed and not running.
if [ -d "/usr/local/novnc" ] && [ "\$(ps -ef | grep /usr/local/novnc/noVNC*/utils/launch.sh | grep -v grep)" = "" ]; then if [ -d "/usr/local/novnc" ] && [ "\$(ps -ef | grep /usr/local/novnc/noVNC*/utils/launch.sh | grep -v grep)" = "" ]; then
keepRunningInBackground "noVNC" sudoIf "/usr/local/novnc/noVNC*/utils/launch.sh --listen ${NOVNC_PORT} --vnc localhost:${VNC_PORT}" keepRunningInBackground "noVNC" sudoIf "/usr/local/novnc/noVNC*/utils/launch.sh --listen ${NOVNC_PORT} --vnc localhost:${VNC_PORT}"
log "noVNC started." log "noVNC started."
@ -387,6 +389,9 @@ if [ "${USERNAME}" != "root" ]; then
chown -R ${USERNAME} /home/${USERNAME}/.Xmodmap /home/${USERNAME}/.fluxbox chown -R ${USERNAME} /home/${USERNAME}/.Xmodmap /home/${USERNAME}/.fluxbox
fi fi
# Clean up
rm -rf /var/lib/apt/lists/*
cat << EOF cat << EOF

View file

@ -1,27 +0,0 @@
## Supporting bind mounts from the workspace folder
A common question that comes up is how you can use `bind` mounts from the Docker CLI from within the a dev container using this Feature (e.g. via `-v`). The trick is that, since you're actually using the Docker engine sitting outside of the container, the filesystem paths will be different than those in the container. You need to use the **host**'s paths instead.
> **Note:** The docker-from-docker approach does not currently enable bind mounting locations outside of the workspace folder.
### GitHub Codespaces
In GitHub Codespaces, the workspace folder should work with bind mounts by default, so no further action is required.
### Remote - Containers
A simple way to do this is to put `${localWorkspaceFolder}` in an environment variable that you then use when doing bind mounts inside the container.
Add the following to `devcontainer.json`:
```json
"remoteEnv": { "LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}" }
```
Then reference the env var when running Docker commands from the terminal inside the container.
```bash
docker run -it --rm -v ${LOCAL_WORKSPACE_FOLDER}:/workspace debian bash
```
> **Note:** There is no `${localWorkspaceFolder}` when using the **Clone Repository in Container Volume** command ([info](https://github.com/microsoft/vscode-remote-release/issues/6160#issuecomment-1014701007)).

View file

@ -1,54 +0,0 @@
# Docker (Docker-from-Docker) (docker-from-docker)
## Example Usage
```json
"features": {
"ghcr.io/devcontainers/features/docker-from-docker:1": {
"version": "latest"
}
}
```
## Options
| Options Id | Description | Type | Default Value |
|-----|-----|-----|-----|
| version | Select or enter a Docker/Moby CLI version. (Availability can vary by OS version.) | string | latest |
| moby | Install OSS Moby build instead of Docker CE | boolean | true |
| dockerDashComposeVersion | Compose version to use for docker-compose (v1 or v2) | string | v1 |
## Supporting bind mounts from the workspace folder
A common question that comes up is how you can use `bind` mounts from the Docker CLI from within the a dev container using this Feature (e.g. via `-v`). The trick is that, since you're actually using the Docker engine sitting outside of the container, the filesystem paths will be different than those in the container. You need to use the **host**'s paths instead.
> **Note:** The docker-from-docker approach does not currently enable bind mounting locations outside of the workspace folder.
### GitHub Codespaces
In GitHub Codespaces, the workspace folder should work with bind mounts by default, so no further action is required.
### Remote - Containers
A simple way to do this is to put `${localWorkspaceFolder}` in an environment variable that you then use when doing bind mounts inside the container.
Add the following to `devcontainer.json`:
```json
"remoteEnv": { "LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}" }
```
Then reference the env var when running Docker commands from the terminal inside the container.
```bash
docker run -it --rm -v ${LOCAL_WORKSPACE_FOLDER}:/workspace debian bash
```
> **Note:** There is no `${localWorkspaceFolder}` when using the **Clone Repository in Container Volume** command ([info](https://github.com/microsoft/vscode-remote-release/issues/6160#issuecomment-1014701007)).
---
_Note: This file was auto-generated from the [devcontainer-feature.json](https://github.com/devcontainers/features/blob/main/src/docker-from-docker/devcontainer-feature.json). Add additional notes to a `NOTES.md`._

View file

@ -0,0 +1,16 @@
## Limitations
This docker-in-docker Dev Container Feature is roughly based on the [official docker-in-docker wrapper script](https://github.com/moby/moby/blob/master/hack/dind) that is part of the [Moby project](https://mobyproject.org/). With this in mind:
* As the name implies, the Feature is expected to work when the host is running Docker (or the OSS Moby container engine it is built on). It may be possible to get running in other container engines, but it has not been tested with them.
* The host and the container must be running on the same chip architecture. You will not be able to use it with an emulated x86 image with Docker Desktop on an Apple Silicon Mac, like in this example:
```
FROM --platform=linux/amd64 mcr.microsoft.com/devcontainers/typescript-node:16
```
See [Issue #219](https://github.com/devcontainers/features/issues/219) for more details.
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.

View file

@ -7,9 +7,7 @@ Create child containers *inside* a container, independent from the host's docker
```json ```json
"features": { "features": {
"ghcr.io/devcontainers/features/docker-in-docker:1": { "ghcr.io/devcontainers/features/docker-in-docker:2": {}
"version": "latest"
}
} }
``` ```
@ -19,8 +17,33 @@ Create child containers *inside* a container, independent from the host's docker
|-----|-----|-----|-----| |-----|-----|-----|-----|
| version | Select or enter a Docker/Moby Engine version. (Availability can vary by OS version.) | string | latest | | version | Select or enter a Docker/Moby Engine version. (Availability can vary by OS version.) | string | latest |
| moby | Install OSS Moby build instead of Docker CE | boolean | true | | moby | Install OSS Moby build instead of Docker CE | boolean | true |
| dockerDashComposeVersion | Default version of Docker Compose (v1 or v2) | string | v1 | | dockerDashComposeVersion | Default version of Docker Compose (v1 or v2 or none) | string | v1 |
| azureDnsAutoDetection | Allow automatically setting the dockerd DNS server when the installation script detects it is running in Azure | boolean | true |
| dockerDefaultAddressPool | Define default address pools for Docker networks. e.g. base=192.168.0.0/16,size=24 | string | - |
| installDockerBuildx | Install Docker Buildx | boolean | true |
## Customizations
### VS Code Extensions
- `ms-azuretools.vscode-docker`
## Limitations
This docker-in-docker Dev Container Feature is roughly based on the [official docker-in-docker wrapper script](https://github.com/moby/moby/blob/master/hack/dind) that is part of the [Moby project](https://mobyproject.org/). With this in mind:
* As the name implies, the Feature is expected to work when the host is running Docker (or the OSS Moby container engine it is built on). It may be possible to get running in other container engines, but it has not been tested with them.
* The host and the container must be running on the same chip architecture. You will not be able to use it with an emulated x86 image with Docker Desktop on an Apple Silicon Mac, like in this example:
```
FROM --platform=linux/amd64 mcr.microsoft.com/devcontainers/typescript-node:16
```
See [Issue #219](https://github.com/devcontainers/features/issues/219) for more details.
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.
--- ---

View file

@ -1,6 +1,6 @@
{ {
"id": "docker-in-docker", "id": "docker-in-docker",
"version": "1.0.5", "version": "2.7.1",
"name": "Docker (Docker-in-Docker)", "name": "Docker (Docker-in-Docker)",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/docker-in-docker", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/docker-in-docker",
"description": "Create child containers *inside* a container, independent from the host's docker instance. Installs Docker extension in the container along with needed CLIs.", "description": "Create child containers *inside* a container, independent from the host's docker instance. Installs Docker extension in the container along with needed CLIs.",
@ -23,16 +23,28 @@
"dockerDashComposeVersion": { "dockerDashComposeVersion": {
"type": "string", "type": "string",
"enum": [ "enum": [
"none",
"v1", "v1",
"v2" "v2"
], ],
"default": "v1", "default": "v1",
"description": "Default version of Docker Compose (v1 or v2)" "description": "Default version of Docker Compose (v1 or v2 or none)"
}, },
"azureDnsAutoDetection": { "azureDnsAutoDetection": {
"type": "boolean", "type": "boolean",
"default": true, "default": true,
"description": "Allow automatically setting the dockerd DNS server when the installation script detects it is running in Azure" "description": "Allow automatically setting the dockerd DNS server when the installation script detects it is running in Azure"
},
"dockerDefaultAddressPool": {
"type": "string",
"default": "",
"proposals": [],
"description": "Define default address pools for Docker networks. e.g. base=192.168.0.0/16,size=24"
},
"installDockerBuildx": {
"type": "boolean",
"default": true,
"description": "Install Docker Buildx"
} }
}, },
"entrypoint": "/usr/local/share/docker-init.sh", "entrypoint": "/usr/local/share/docker-init.sh",
@ -49,9 +61,12 @@
}, },
"mounts": [ "mounts": [
{ {
"source": "dind-var-lib-docker", "source": "dind-var-lib-docker-${devcontainerId}",
"target": "/var/lib/docker", "target": "/var/lib/docker",
"type": "volume" "type": "volume"
} }
],
"installsAfter": [
"ghcr.io/devcontainers/features/common-utils"
] ]
} }

View file

@ -5,24 +5,26 @@
#------------------------------------------------------------------------------------------------------------- #-------------------------------------------------------------------------------------------------------------
# #
# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/docker-in-docker.md # Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/docker-in-docker.md
# Maintainer: The VS Code and Codespaces Teams # Maintainer: The Dev Container spec maintainers
DOCKER_VERSION=${VERSION:-"latest"} # The Docker/Moby Engine + CLI should match in version DOCKER_VERSION="${VERSION:-"latest"}" # The Docker/Moby Engine + CLI should match in version
USE_MOBY=${MOBY:-"true"} USE_MOBY="${MOBY:-"true"}"
DOCKER_DASH_COMPOSE_VERSION=${DOCKERDASHCOMPOSEVERSION:-"v1"} # v1 or v2 DOCKER_DASH_COMPOSE_VERSION="${DOCKERDASHCOMPOSEVERSION:-"v1"}" # v1 or v2 or none
AZURE_DNS_AUTO_DETECTION=${AZUREDNSAUTODETECTION:-"true"} AZURE_DNS_AUTO_DETECTION="${AZUREDNSAUTODETECTION:-"true"}"
DOCKER_DEFAULT_ADDRESS_POOL="${DOCKERDEFAULTADDRESSPOOL}"
ENABLE_NONROOT_DOCKER=${ENABLE_NONROOT_DOCKER:-"true"} USERNAME="${USERNAME:-"${_REMOTE_USER:-"automatic"}"}"
USERNAME=${USERNAME:-"automatic"} INSTALL_DOCKER_BUILDX="${INSTALLDOCKERBUILDX:-"true"}"
MICROSOFT_GPG_KEYS_URI="https://packages.microsoft.com/keys/microsoft.asc" MICROSOFT_GPG_KEYS_URI="https://packages.microsoft.com/keys/microsoft.asc"
DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES="buster bullseye bionic focal jammy" DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES="bookworm buster bullseye bionic focal jammy"
DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES="buster bullseye bionic focal hirsute impish jammy" DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES="bookworm buster bullseye bionic focal hirsute impish jammy"
# Default: Exit on any failure. # Default: Exit on any failure.
set -e set -e
# Clean up
rm -rf /var/lib/apt/lists/*
# Setup STDERR. # Setup STDERR.
err() { err() {
echo "(!) $*" >&2 echo "(!) $*" >&2
@ -55,25 +57,12 @@ elif [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then
USERNAME=root USERNAME=root
fi fi
# Get central common setting
get_common_setting() {
if [ "${common_settings_file_loaded}" != "true" ]; then
curl -sfL "https://aka.ms/vscode-dev-containers/script-library/settings.env" 2>/dev/null -o /tmp/vsdc-settings.env || echo "Could not download settings file. Skipping."
common_settings_file_loaded=true
fi
if [ -f "/tmp/vsdc-settings.env" ]; then
local multi_line=""
if [ "$2" = "true" ]; then multi_line="-z"; fi
local result="$(grep ${multi_line} -oP "$1=\"?\K[^\"]+" /tmp/vsdc-settings.env | tr -d '\0')"
if [ ! -z "${result}" ]; then declare -g $1="${result}"; fi
fi
echo "$1=${!1}"
}
apt_get_update() apt_get_update()
{ {
echo "Running apt-get update..." if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then
apt-get update -y echo "Running apt-get update..."
apt-get update -y
fi
} }
# Checks if packages are installed and installs them if not # Checks if packages are installed and installs them if not
@ -131,10 +120,8 @@ export DEBIAN_FRONTEND=noninteractive
# Fetch host/container arch. # Fetch host/container arch.
architecture="$(dpkg --print-architecture)" architecture="$(dpkg --print-architecture)"
# Check if distro is suppported # Check if distro is supported
if [ "${USE_MOBY}" = "true" ]; then if [ "${USE_MOBY}" = "true" ]; then
# 'get_common_setting' allows attribute to be updated remotely
get_common_setting DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES
if [[ "${DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES}" != *"${VERSION_CODENAME}"* ]]; then if [[ "${DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES}" != *"${VERSION_CODENAME}"* ]]; then
err "Unsupported distribution version '${VERSION_CODENAME}'. To resolve, either: (1) set feature option '\"moby\": false' , or (2) choose a compatible OS distribution" err "Unsupported distribution version '${VERSION_CODENAME}'. To resolve, either: (1) set feature option '\"moby\": false' , or (2) choose a compatible OS distribution"
err "Support distributions include: ${DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES}" err "Support distributions include: ${DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES}"
@ -142,7 +129,6 @@ if [ "${USE_MOBY}" = "true" ]; then
fi fi
echo "Distro codename '${VERSION_CODENAME}' matched filter '${DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES}'" echo "Distro codename '${VERSION_CODENAME}' matched filter '${DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES}'"
else else
get_common_setting DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES
if [[ "${DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES}" != *"${VERSION_CODENAME}"* ]]; then if [[ "${DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES}" != *"${VERSION_CODENAME}"* ]]; then
err "Unsupported distribution version '${VERSION_CODENAME}'. To resolve, please choose a compatible OS distribution" err "Unsupported distribution version '${VERSION_CODENAME}'. To resolve, please choose a compatible OS distribution"
err "Support distributions include: ${DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES}" err "Support distributions include: ${DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES}"
@ -152,10 +138,9 @@ else
fi fi
# Install dependencies # Install dependencies
check_packages apt-transport-https curl ca-certificates pigz iptables gnupg2 dirmngr check_packages apt-transport-https curl ca-certificates pigz iptables gnupg2 dirmngr wget
if ! type git > /dev/null 2>&1; then if ! type git > /dev/null 2>&1; then
apt_get_update check_packages git
apt-get -y install git
fi fi
# Swap to legacy iptables for compatibility # Swap to legacy iptables for compatibility
@ -174,7 +159,6 @@ if [ "${USE_MOBY}" = "true" ]; then
cli_package_name="moby-cli" cli_package_name="moby-cli"
# Import key safely and import Microsoft apt repo # Import key safely and import Microsoft apt repo
get_common_setting MICROSOFT_GPG_KEYS_URI
curl -sSL ${MICROSOFT_GPG_KEYS_URI} | gpg --dearmor > /usr/share/keyrings/microsoft-archive-keyring.gpg curl -sSL ${MICROSOFT_GPG_KEYS_URI} | gpg --dearmor > /usr/share/keyrings/microsoft-archive-keyring.gpg
echo "deb [arch=${architecture} signed-by=/usr/share/keyrings/microsoft-archive-keyring.gpg] https://packages.microsoft.com/repos/microsoft-${ID}-${VERSION_CODENAME}-prod ${VERSION_CODENAME} main" > /etc/apt/sources.list.d/microsoft.list echo "deb [arch=${architecture} signed-by=/usr/share/keyrings/microsoft-archive-keyring.gpg] https://packages.microsoft.com/repos/microsoft-${ID}-${VERSION_CODENAME}-prod ${VERSION_CODENAME} main" > /etc/apt/sources.list.d/microsoft.list
else else
@ -239,77 +223,107 @@ fi
echo "Finished installing docker / moby!" echo "Finished installing docker / moby!"
# Install Docker Compose if not already installed and is on a supported architecture # If 'docker-compose' command is to be included
if type docker-compose > /dev/null 2>&1; then if [ "${DOCKER_DASH_COMPOSE_VERSION}" != "none" ]; then
echo "Docker Compose v1 already installed." # Install Docker Compose if not already installed and is on a supported architecture
else if type docker-compose > /dev/null 2>&1; then
target_compose_arch="${architecture}" echo "Docker Compose v1 already installed."
if [ "${target_compose_arch}" = "amd64" ]; then
target_compose_arch="x86_64"
fi
if [ "${target_compose_arch}" != "x86_64" ]; then
# Use pip to get a version that runs on this architecture
if ! dpkg -s python3-minimal python3-pip libffi-dev python3-venv > /dev/null 2>&1; then
apt_get_update
apt-get -y install python3-minimal python3-pip libffi-dev python3-venv
fi
export PIPX_HOME=/usr/local/pipx
mkdir -p ${PIPX_HOME}
export PIPX_BIN_DIR=/usr/local/bin
export PYTHONUSERBASE=/tmp/pip-tmp
export PIP_CACHE_DIR=/tmp/pip-tmp/cache
pipx_bin=pipx
if ! type pipx > /dev/null 2>&1; then
pip3 install --disable-pip-version-check --no-cache-dir --user pipx
pipx_bin=/tmp/pip-tmp/bin/pipx
fi
${pipx_bin} install --pip-args '--no-cache-dir --force-reinstall' docker-compose
rm -rf /tmp/pip-tmp
else else
compose_v1_version="1" target_compose_arch="${architecture}"
find_version_from_git_tags compose_v1_version "https://github.com/docker/compose" "tags/" if [ "${target_compose_arch}" = "amd64" ]; then
echo "(*) Installing docker-compose ${compose_v1_version}..." target_compose_arch="x86_64"
curl -fsSL "https://github.com/docker/compose/releases/download/${compose_v1_version}/docker-compose-Linux-x86_64" -o /usr/local/bin/docker-compose fi
chmod +x /usr/local/bin/docker-compose if [ "${target_compose_arch}" != "x86_64" ]; then
# Use pip to get a version that runs on this architecture
check_packages python3-minimal python3-pip libffi-dev python3-venv
export PIPX_HOME=/usr/local/pipx
mkdir -p ${PIPX_HOME}
export PIPX_BIN_DIR=/usr/local/bin
export PYTHONUSERBASE=/tmp/pip-tmp
export PIP_CACHE_DIR=/tmp/pip-tmp/cache
pipx_bin=pipx
if ! type pipx > /dev/null 2>&1; then
pip3 install --disable-pip-version-check --no-cache-dir --user pipx
pipx_bin=/tmp/pip-tmp/bin/pipx
fi
set +e
${pipx_bin} install --pip-args '--no-cache-dir --force-reinstall' docker-compose
exit_code=$?
set -e
if [ ${exit_code} -ne 0 ]; then
# Temporary: https://github.com/devcontainers/features/issues/616
# See https://github.com/yaml/pyyaml/issues/601
echo "(*) Failed to install docker-compose via pipx. Trying via pip3..."
export PYTHONUSERBASE=/usr/local
pip3 install --disable-pip-version-check --no-cache-dir --user "Cython<3.0" pyyaml wheel docker-compose --no-build-isolation
fi
rm -rf /tmp/pip-tmp
else
compose_v1_version="1"
find_version_from_git_tags compose_v1_version "https://github.com/docker/compose" "tags/"
echo "(*) Installing docker-compose ${compose_v1_version}..."
curl -fsSL "https://github.com/docker/compose/releases/download/${compose_v1_version}/docker-compose-Linux-x86_64" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
fi
fi fi
fi
# Install docker-compose switch if not already installed - https://github.com/docker/compose-switch#manual-installation # Install docker-compose switch if not already installed - https://github.com/docker/compose-switch#manual-installation
current_v1_compose_path="$(which docker-compose)" current_v1_compose_path="$(which docker-compose)"
target_v1_compose_path="$(dirname "${current_v1_compose_path}")/docker-compose-v1" target_v1_compose_path="$(dirname "${current_v1_compose_path}")/docker-compose-v1"
if ! type compose-switch > /dev/null 2>&1; then if ! type compose-switch > /dev/null 2>&1; then
echo "(*) Installing compose-switch..." echo "(*) Installing compose-switch..."
compose_switch_version="latest" compose_switch_version="latest"
find_version_from_git_tags compose_switch_version "https://github.com/docker/compose-switch" find_version_from_git_tags compose_switch_version "https://github.com/docker/compose-switch"
curl -fsSL "https://github.com/docker/compose-switch/releases/download/v${compose_switch_version}/docker-compose-linux-${architecture}" -o /usr/local/bin/compose-switch curl -fsSL "https://github.com/docker/compose-switch/releases/download/v${compose_switch_version}/docker-compose-linux-${architecture}" -o /usr/local/bin/compose-switch
chmod +x /usr/local/bin/compose-switch chmod +x /usr/local/bin/compose-switch
# TODO: Verify checksum once available: https://github.com/docker/compose-switch/issues/11 # TODO: Verify checksum once available: https://github.com/docker/compose-switch/issues/11
# Setup v1 CLI as alternative in addition to compose-switch (which maps to v2) # Setup v1 CLI as alternative in addition to compose-switch (which maps to v2)
mv "${current_v1_compose_path}" "${target_v1_compose_path}" mv "${current_v1_compose_path}" "${target_v1_compose_path}"
update-alternatives --install /usr/local/bin/docker-compose docker-compose /usr/local/bin/compose-switch 99 update-alternatives --install /usr/local/bin/docker-compose docker-compose /usr/local/bin/compose-switch 99
update-alternatives --install /usr/local/bin/docker-compose docker-compose "${target_v1_compose_path}" 1 update-alternatives --install /usr/local/bin/docker-compose docker-compose "${target_v1_compose_path}" 1
fi fi
if [ "${DOCKER_DASH_COMPOSE_VERSION}" = "v1" ]; then if [ "${DOCKER_DASH_COMPOSE_VERSION}" = "v1" ]; then
update-alternatives --set docker-compose "${target_v1_compose_path}" update-alternatives --set docker-compose "${target_v1_compose_path}"
else else
update-alternatives --set docker-compose /usr/local/bin/compose-switch update-alternatives --set docker-compose /usr/local/bin/compose-switch
fi
fi fi
# If init file already exists, exit # If init file already exists, exit
if [ -f "/usr/local/share/docker-init.sh" ]; then if [ -f "/usr/local/share/docker-init.sh" ]; then
echo "/usr/local/share/docker-init.sh already exists, so exiting." echo "/usr/local/share/docker-init.sh already exists, so exiting."
# Clean up
rm -rf /var/lib/apt/lists/*
exit 0 exit 0
fi fi
echo "docker-init doesnt exist, adding..." echo "docker-init doesn't exist, adding..."
# Add user to the docker group if ! cat /etc/group | grep -e "^docker:" > /dev/null 2>&1; then
if [ "${ENABLE_NONROOT_DOCKER}" = "true" ]; then groupadd -r docker
if ! getent group docker > /dev/null 2>&1; then fi
groupadd docker
fi
usermod -aG docker ${USERNAME} usermod -aG docker ${USERNAME}
if [ "${INSTALL_DOCKER_BUILDX}" = "true" ]; then
buildx_version="latest"
find_version_from_git_tags buildx_version "https://github.com/docker/buildx" "refs/tags/v"
echo "(*) Installing buildx ${buildx_version}..."
buildx_file_name="buildx-v${buildx_version}.linux-${architecture}"
cd /tmp && wget "https://github.com/docker/buildx/releases/download/v${buildx_version}/${buildx_file_name}"
mkdir -p ${_REMOTE_USER_HOME}/.docker/cli-plugins
mv ${buildx_file_name} ${_REMOTE_USER_HOME}/.docker/cli-plugins/docker-buildx
chmod +x ${_REMOTE_USER_HOME}/.docker/cli-plugins/docker-buildx
chown -R "${USERNAME}:docker" "${_REMOTE_USER_HOME}/.docker"
chmod -R g+r+w "${_REMOTE_USER_HOME}/.docker"
find "${_REMOTE_USER_HOME}/.docker" -type d -print0 | xargs -n 1 -0 chmod g+s
fi fi
tee /usr/local/share/docker-init.sh > /dev/null \ tee /usr/local/share/docker-init.sh > /dev/null \
@ -322,18 +336,18 @@ tee /usr/local/share/docker-init.sh > /dev/null \
set -e set -e
AZURE_DNS_AUTO_DETECTION=$AZURE_DNS_AUTO_DETECTION AZURE_DNS_AUTO_DETECTION=${AZURE_DNS_AUTO_DETECTION}
DOCKER_DEFAULT_ADDRESS_POOL=${DOCKER_DEFAULT_ADDRESS_POOL}
EOF EOF
tee -a /usr/local/share/docker-init.sh > /dev/null \ tee -a /usr/local/share/docker-init.sh > /dev/null \
<< 'EOF' << 'EOF'
dockerd_start="$(cat << 'INNEREOF' dockerd_start="AZURE_DNS_AUTO_DETECTION=${AZURE_DNS_AUTO_DETECTION} DOCKER_DEFAULT_ADDRESS_POOL=${DOCKER_DEFAULT_ADDRESS_POOL} $(cat << 'INNEREOF'
# explicitly remove dockerd and containerd PID file to ensure that it can start properly if it was stopped uncleanly # explicitly remove dockerd and containerd PID file to ensure that it can start properly if it was stopped uncleanly
# ie: docker kill <ID>
find /run /var/run -iname 'docker*.pid' -delete || : find /run /var/run -iname 'docker*.pid' -delete || :
find /run /var/run -iname 'container*.pid' -delete || : find /run /var/run -iname 'container*.pid' -delete || :
## Dind wrapper script from docker team, adapted to a function # -- Start: dind wrapper script --
# Maintained: https://github.com/moby/moby/blob/master/hack/dind # Maintained: https://github.com/moby/moby/blob/master/hack/dind
export container=docker export container=docker
@ -350,45 +364,109 @@ dockerd_start="$(cat << 'INNEREOF'
mount -t tmpfs none /tmp mount -t tmpfs none /tmp
fi fi
# cgroup v2: enable nesting set_cgroup_nesting()
if [ -f /sys/fs/cgroup/cgroup.controllers ]; then {
# move the processes from the root group to the /init group, # cgroup v2: enable nesting
# otherwise writing subtree_control fails with EBUSY. if [ -f /sys/fs/cgroup/cgroup.controllers ]; then
# An error during moving non-existent process (i.e., "cat") is ignored. # move the processes from the root group to the /init group,
mkdir -p /sys/fs/cgroup/init # otherwise writing subtree_control fails with EBUSY.
xargs -rn1 < /sys/fs/cgroup/cgroup.procs > /sys/fs/cgroup/init/cgroup.procs || : # An error during moving non-existent process (i.e., "cat") is ignored.
# enable controllers mkdir -p /sys/fs/cgroup/init
sed -e 's/ / +/g' -e 's/^/+/' < /sys/fs/cgroup/cgroup.controllers \ xargs -rn1 < /sys/fs/cgroup/cgroup.procs > /sys/fs/cgroup/init/cgroup.procs || :
> /sys/fs/cgroup/cgroup.subtree_control # enable controllers
fi sed -e 's/ / +/g' -e 's/^/+/' < /sys/fs/cgroup/cgroup.controllers \
## Dind wrapper over. > /sys/fs/cgroup/cgroup.subtree_control
fi
}
# Set cgroup nesting, retrying if necessary
retry_cgroup_nesting=0
until [ "${retry_cgroup_nesting}" -eq "5" ];
do
set +e
set_cgroup_nesting
if [ $? -ne 0 ]; then
echo "(*) cgroup v2: Failed to enable nesting, retrying..."
else
break
fi
retry_cgroup_nesting=`expr $retry_cgroup_nesting + 1`
set -e
done
# -- End: dind wrapper script --
# Handle DNS # Handle DNS
set +e set +e
cat /etc/resolv.conf | grep -i 'internal.cloudapp.net' cat /etc/resolv.conf | grep -i 'internal.cloudapp.net' > /dev/null 2>&1
if [ $? -eq 0 ] && [ ${AZURE_DNS_AUTO_DETECTION} = "true" ] if [ $? -eq 0 ] && [ "${AZURE_DNS_AUTO_DETECTION}" = "true" ]
then then
echo "Setting dockerd Azure DNS." echo "Setting dockerd Azure DNS."
CUSTOMDNS="--dns 168.63.129.16" CUSTOMDNS="--dns 168.63.129.16"
else else
echo "Not setting dockerd DNS manually." echo "Not setting dockerd DNS manually."
CUSTOMDNS="" CUSTOMDNS=""
fi fi
set -e set -e
if [ -z "$DOCKER_DEFAULT_ADDRESS_POOL" ]
then
DEFAULT_ADDRESS_POOL=""
else
DEFAULT_ADDRESS_POOL="--default-address-pool $DOCKER_DEFAULT_ADDRESS_POOL"
fi
# Start docker/moby engine # Start docker/moby engine
( dockerd $CUSTOMDNS > /tmp/dockerd.log 2>&1 ) & ( dockerd $CUSTOMDNS $DEFAULT_ADDRESS_POOL > /tmp/dockerd.log 2>&1 ) &
INNEREOF INNEREOF
)" )"
# Start using sudo if not invoked as root sudo_if() {
if [ "$(id -u)" -ne 0 ]; then COMMAND="$*"
sudo /bin/sh -c "${dockerd_start}"
else
eval "${dockerd_start}"
fi
set +e if [ "$(id -u)" -ne 0 ]; then
sudo $COMMAND
else
$COMMAND
fi
}
retry_docker_start_count=0
docker_ok="false"
until [ "${docker_ok}" = "true" ] || [ "${retry_docker_start_count}" -eq "5" ];
do
# Start using sudo if not invoked as root
if [ "$(id -u)" -ne 0 ]; then
sudo /bin/sh -c "${dockerd_start}"
else
eval "${dockerd_start}"
fi
retry_count=0
until [ "${docker_ok}" = "true" ] || [ "${retry_count}" -eq "5" ];
do
sleep 1s
set +e
docker info > /dev/null 2>&1 && docker_ok="true"
set -e
retry_count=`expr $retry_count + 1`
done
if [ "${docker_ok}" != "true" ] && [ "${retry_docker_start_count}" != "4" ]; then
echo "(*) Failed to start docker, retrying..."
set +e
sudo_if pkill dockerd
sudo_if pkill containerd
set -e
fi
retry_docker_start_count=`expr $retry_docker_start_count + 1`
done
# Execute whatever commands were passed in (if any). This allows us # Execute whatever commands were passed in (if any). This allows us
# to set this script to ENTRYPOINT while still executing the default CMD. # to set this script to ENTRYPOINT while still executing the default CMD.
@ -398,4 +476,7 @@ EOF
chmod +x /usr/local/share/docker-init.sh chmod +x /usr/local/share/docker-init.sh
chown ${USERNAME}:root /usr/local/share/docker-init.sh chown ${USERNAME}:root /usr/local/share/docker-init.sh
# Clean up
rm -rf /var/lib/apt/lists/*
echo 'docker-in-docker-debian script has completed!' echo 'docker-in-docker-debian script has completed!'

View file

@ -0,0 +1,61 @@
## Limitations
- As the name implies, the Feature is expected to work when the host is running Docker (or the OSS Moby container engine it is built on). It may be possible to get running in other container engines, but it has not been tested with them.
- The host and the container must be running on the same chip architecture. You will not be able to use it with an emulated x86 image with Docker Desktop on an Apple Silicon Mac, for example.
- This approach does not currently enable bind mounting the workspace folder by default, and cannot support folders outside of the workspace folder. Consider whether the [Docker-in-Docker Feature](../docker-in-docker) would better meet your needs given it does not have this limitation.
## Supporting bind mounts from the workspace folder
A common question that comes up is how you can use `bind` mounts from the Docker CLI from within the a dev container using this Feature (e.g. via `-v`). If you cannot use the [Docker-in-Docker Feature](../docker-in-docker), the only way to work around this is to use the **host**'s folder paths instead of the container's paths. There are 2 ways to do this
### 1. Use the `${localWorkspaceFolder}` as environment variable in your code
1. Add the following to `devcontainer.json`:
```json
"remoteEnv": { "LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}" }
```
2. Usage with Docker commands
```bash
docker run -it --rm -v ${LOCAL_WORKSPACE_FOLDER}:/workspace debian bash
```
3. Usage with Docker-compose
```yaml
version: "3.9"
services:
debian:
image: debian
volumes:
- ${LOCAL_WORKSPACE_FOLDER:-./}:/workspace
```
- The defaults value `./` is added so that the `docker-compose.yaml` file can work when it is run outside of the container
### Change the workspace to `${localWorkspaceFolder}`
- This is useful if we don't want to edit the `docker-compose.yaml` file
1. Add the following to `devcontainer.json`
```json
"workspaceFolder": "${localWorkspaceFolder}",
"workspaceMount": "source=${localWorkspaceFolder},target=${localWorkspaceFolder},type=bind"
```
2. Rebuild the container.
3. When the container first started with this settings, select the Workspace with the absolute path to the working directory inside the container
4. Docker commands with bind mount should work as they did outside of the devcontainer
> **Note:** There is no `${localWorkspaceFolder}` when using the **Clone Repository in Container Volume** command in the VS Code Dev Containers extension ([info](https://github.com/microsoft/vscode-remote-release/issues/6160#issuecomment-1014701007)).
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.

View file

@ -0,0 +1,96 @@
### **IMPORTANT NOTE**
- **Ids used to publish this Feature in the past - 'docker-from-docker'**
# Docker (docker-outside-of-docker) (docker-outside-of-docker)
Re-use the host docker socket, adding the Docker CLI to a container. Feature invokes a script to enable using a forwarded Docker socket within a container to run Docker commands.
## Example Usage
```json
"features": {
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}
}
```
## Options
| Options Id | Description | Type | Default Value |
|-----|-----|-----|-----|
| version | Select or enter a Docker/Moby CLI version. (Availability can vary by OS version.) | string | latest |
| moby | Install OSS Moby build instead of Docker CE | boolean | true |
| dockerDashComposeVersion | Compose version to use for docker-compose (v1 or v2 or none) | string | v2 |
| installDockerBuildx | Install Docker Buildx | boolean | true |
## Customizations
### VS Code Extensions
- `ms-azuretools.vscode-docker`
## Limitations
- As the name implies, the Feature is expected to work when the host is running Docker (or the OSS Moby container engine it is built on). It may be possible to get running in other container engines, but it has not been tested with them.
- The host and the container must be running on the same chip architecture. You will not be able to use it with an emulated x86 image with Docker Desktop on an Apple Silicon Mac, for example.
- This approach does not currently enable bind mounting the workspace folder by default, and cannot support folders outside of the workspace folder. Consider whether the [Docker-in-Docker Feature](../docker-in-docker) would better meet your needs given it does not have this limitation.
## Supporting bind mounts from the workspace folder
A common question that comes up is how you can use `bind` mounts from the Docker CLI from within the a dev container using this Feature (e.g. via `-v`). If you cannot use the [Docker-in-Docker Feature](../docker-in-docker), the only way to work around this is to use the **host**'s folder paths instead of the container's paths. There are 2 ways to do this
### 1. Use the `${localWorkspaceFolder}` as environment variable in your code
1. Add the following to `devcontainer.json`:
```json
"remoteEnv": { "LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}" }
```
2. Usage with Docker commands
```bash
docker run -it --rm -v ${LOCAL_WORKSPACE_FOLDER}:/workspace debian bash
```
3. Usage with Docker-compose
```yaml
version: "3.9"
services:
debian:
image: debian
volumes:
- ${LOCAL_WORKSPACE_FOLDER:-./}:/workspace
```
- The defaults value `./` is added so that the `docker-compose.yaml` file can work when it is run outside of the container
### Change the workspace to `${localWorkspaceFolder}`
- This is useful if we don't want to edit the `docker-compose.yaml` file
1. Add the following to `devcontainer.json`
```json
"workspaceFolder": "${localWorkspaceFolder}",
"workspaceMount": "source=${localWorkspaceFolder},target=${localWorkspaceFolder},type=bind"
```
2. Rebuild the container.
3. When the container first started with this settings, select the Workspace with the absolute path to the working directory inside the container
4. Docker commands with bind mount should work as they did outside of the devcontainer
> **Note:** There is no `${localWorkspaceFolder}` when using the **Clone Repository in Container Volume** command in the VS Code Dev Containers extension ([info](https://github.com/microsoft/vscode-remote-release/issues/6160#issuecomment-1014701007)).
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.
---
_Note: This file was auto-generated from the [devcontainer-feature.json](https://github.com/devcontainers/features/blob/main/src/docker-outside-of-docker/devcontainer-feature.json). Add additional notes to a `NOTES.md`._

View file

@ -1,9 +1,9 @@
{ {
"id": "docker-from-docker", "id": "docker-outside-of-docker",
"version": "1.0.4", "version": "1.3.1",
"name": "Docker (Docker-from-Docker)", "name": "Docker (docker-outside-of-docker)",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/docker-from-docker", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/docker-outside-of-docker",
"descripton": "Re-use the host docker socket, adding the Docker CLI to a container. Feature invokes a script to enable using a forwarded Docker socket within a container to run Docker commands.", "description": "Re-use the host docker socket, adding the Docker CLI to a container. Feature invokes a script to enable using a forwarded Docker socket within a container to run Docker commands.",
"options": { "options": {
"version": { "version": {
"type": "string", "type": "string",
@ -23,17 +23,20 @@
"dockerDashComposeVersion": { "dockerDashComposeVersion": {
"type": "string", "type": "string",
"enum": [ "enum": [
"none",
"v1", "v1",
"v2" "v2"
], ],
"default": "v1", "default": "v2",
"description": "Compose version to use for docker-compose (v1 or v2)" "description": "Compose version to use for docker-compose (v1 or v2 or none)"
},
"installDockerBuildx": {
"type": "boolean",
"default": true,
"description": "Install Docker Buildx"
} }
}, },
"entrypoint": "/usr/local/share/docker-init.sh", "entrypoint": "/usr/local/share/docker-init.sh",
"containerEnv": {
"DOCKER_BUILDKIT": "1"
},
"customizations": { "customizations": {
"vscode": { "vscode": {
"extensions": [ "extensions": [
@ -47,5 +50,11 @@
"target": "/var/run/docker-host.sock", "target": "/var/run/docker-host.sock",
"type": "bind" "type": "bind"
} }
],
"installsAfter": [
"ghcr.io/devcontainers/features/common-utils"
],
"legacyIds": [
"docker-from-docker"
] ]
} }

View file

@ -7,21 +7,25 @@
# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/docker.md # Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/docker.md
# Maintainer: The VS Code and Codespaces Teams # Maintainer: The VS Code and Codespaces Teams
DOCKER_VERSION=${VERSION:-"latest"} DOCKER_VERSION="${VERSION:-"latest"}"
USE_MOBY=${MOBY:-"true"} USE_MOBY="${MOBY:-"true"}"
DOCKER_DASH_COMPOSE_VERSION=${DOCKERDASHCOMPOSEVERSION:-"v1"} # v1 or v2 DOCKER_DASH_COMPOSE_VERSION="${DOCKERDASHCOMPOSEVERSION:-"v1"}" # v1 or v2 or none
ENABLE_NONROOT_DOCKER=${ENABLE_NONROOT_DOCKER:-"true"} ENABLE_NONROOT_DOCKER="${ENABLE_NONROOT_DOCKER:-"true"}"
SOURCE_SOCKET=${SOURCE_SOCKET:-"/var/run/docker-host.sock"} SOURCE_SOCKET="${SOURCE_SOCKET:-"/var/run/docker-host.sock"}"
TARGET_SOCKET=${TARGET_SOCKET:-"/var/run/docker.sock"} TARGET_SOCKET="${TARGET_SOCKET:-"/var/run/docker.sock"}"
USERNAME=${USERNAME:-"automatic"} USERNAME="${USERNAME:-"${_REMOTE_USER:-"automatic"}"}"
INSTALL_DOCKER_BUILDX="${INSTALLDOCKERBUILDX:-"true"}"
MICROSOFT_GPG_KEYS_URI="https://packages.microsoft.com/keys/microsoft.asc" MICROSOFT_GPG_KEYS_URI="https://packages.microsoft.com/keys/microsoft.asc"
DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES="buster bullseye bionic focal jammy" DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES="bookworm buster bullseye bionic focal jammy"
DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES="buster bullseye bionic focal hirsute impish jammy" DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES="bookworm buster bullseye bionic focal hirsute impish jammy"
set -e set -e
# Clean up
rm -rf /var/lib/apt/lists/*
if [ "$(id -u)" -ne 0 ]; then if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1 exit 1
@ -44,25 +48,12 @@ elif [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then
USERNAME=root USERNAME=root
fi fi
# Get central common setting
get_common_setting() {
if [ "${common_settings_file_loaded}" != "true" ]; then
curl -sfL "https://aka.ms/vscode-dev-containers/script-library/settings.env" 2>/dev/null -o /tmp/vsdc-settings.env || echo "Could not download settings file. Skipping."
common_settings_file_loaded=true
fi
if [ -f "/tmp/vsdc-settings.env" ]; then
local multi_line=""
if [ "$2" = "true" ]; then multi_line="-z"; fi
local result="$(grep ${multi_line} -oP "$1=\"?\K[^\"]+" /tmp/vsdc-settings.env | tr -d '\0')"
if [ ! -z "${result}" ]; then declare -g $1="${result}"; fi
fi
echo "$1=${!1}"
}
apt_get_update() apt_get_update()
{ {
echo "Running apt-get update..." if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then
apt-get update -y echo "Running apt-get update..."
apt-get update -y
fi
} }
# Checks if packages are installed and installs them if not # Checks if packages are installed and installs them if not
@ -81,7 +72,7 @@ find_version_from_git_tags() {
local repository=$2 local repository=$2
local prefix=${3:-"tags/v"} local prefix=${3:-"tags/v"}
local separator=${4:-"."} local separator=${4:-"."}
local last_part_optional=${5:-"false"} local last_part_optional=${5:-"false"}
if [ "$(echo "${requested_version}" | grep -o "." | wc -l)" != "2" ]; then if [ "$(echo "${requested_version}" | grep -o "." | wc -l)" != "2" ]; then
local escaped_separator=${separator//./\\.} local escaped_separator=${separator//./\\.}
local last_part local last_part
@ -111,10 +102,9 @@ find_version_from_git_tags() {
export DEBIAN_FRONTEND=noninteractive export DEBIAN_FRONTEND=noninteractive
# Install dependencies # Install dependencies
check_packages apt-transport-https curl ca-certificates gnupg2 dirmngr check_packages apt-transport-https curl ca-certificates gnupg2 dirmngr wget
if ! type git > /dev/null 2>&1; then if ! type git > /dev/null 2>&1; then
apt_get_update check_packages git
apt-get -y install git
fi fi
# Source /etc/os-release to get OS info # Source /etc/os-release to get OS info
@ -122,10 +112,8 @@ fi
# Fetch host/container arch. # Fetch host/container arch.
architecture="$(dpkg --print-architecture)" architecture="$(dpkg --print-architecture)"
# Check if distro is suppported # Check if distro is supported
if [ "${USE_MOBY}" = "true" ]; then if [ "${USE_MOBY}" = "true" ]; then
# 'get_common_setting' allows attribute to be updated remotely
get_common_setting DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES
if [[ "${DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES}" != *"${VERSION_CODENAME}"* ]]; then if [[ "${DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES}" != *"${VERSION_CODENAME}"* ]]; then
err "Unsupported distribution version '${VERSION_CODENAME}'. To resolve, either: (1) set feature option '\"moby\": false' , or (2) choose a compatible OS distribution" err "Unsupported distribution version '${VERSION_CODENAME}'. To resolve, either: (1) set feature option '\"moby\": false' , or (2) choose a compatible OS distribution"
err "Support distributions include: ${DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES}" err "Support distributions include: ${DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES}"
@ -133,7 +121,6 @@ if [ "${USE_MOBY}" = "true" ]; then
fi fi
echo "Distro codename '${VERSION_CODENAME}' matched filter '${DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES}'" echo "Distro codename '${VERSION_CODENAME}' matched filter '${DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES}'"
else else
get_common_setting DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES
if [[ "${DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES}" != *"${VERSION_CODENAME}"* ]]; then if [[ "${DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES}" != *"${VERSION_CODENAME}"* ]]; then
err "Unsupported distribution version '${VERSION_CODENAME}'. To resolve, please choose a compatible OS distribution" err "Unsupported distribution version '${VERSION_CODENAME}'. To resolve, please choose a compatible OS distribution"
err "Support distributions include: ${DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES}" err "Support distributions include: ${DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES}"
@ -148,7 +135,6 @@ if [ "${USE_MOBY}" = "true" ]; then
cli_package_name="moby-cli" cli_package_name="moby-cli"
# Import key safely and import Microsoft apt repo # Import key safely and import Microsoft apt repo
get_common_setting MICROSOFT_GPG_KEYS_URI
curl -sSL ${MICROSOFT_GPG_KEYS_URI} | gpg --dearmor > /usr/share/keyrings/microsoft-archive-keyring.gpg curl -sSL ${MICROSOFT_GPG_KEYS_URI} | gpg --dearmor > /usr/share/keyrings/microsoft-archive-keyring.gpg
echo "deb [arch=${architecture} signed-by=/usr/share/keyrings/microsoft-archive-keyring.gpg] https://packages.microsoft.com/repos/microsoft-${ID}-${VERSION_CODENAME}-prod ${VERSION_CODENAME} main" > /etc/apt/sources.list.d/microsoft.list echo "deb [arch=${architecture} signed-by=/usr/share/keyrings/microsoft-archive-keyring.gpg] https://packages.microsoft.com/repos/microsoft-${ID}-${VERSION_CODENAME}-prod ${VERSION_CODENAME} main" > /etc/apt/sources.list.d/microsoft.list
else else
@ -167,7 +153,7 @@ apt-get update
if [ "${DOCKER_VERSION}" = "latest" ] || [ "${DOCKER_VERSION}" = "lts" ] || [ "${DOCKER_VERSION}" = "stable" ]; then if [ "${DOCKER_VERSION}" = "latest" ] || [ "${DOCKER_VERSION}" = "lts" ] || [ "${DOCKER_VERSION}" = "stable" ]; then
# Empty, meaning grab whatever "latest" is in apt repo # Empty, meaning grab whatever "latest" is in apt repo
cli_version_suffix="" cli_version_suffix=""
else else
# Fetch a valid version from the apt-cache (eg: the Microsoft repo appends +azure, breakfix, etc...) # Fetch a valid version from the apt-cache (eg: the Microsoft repo appends +azure, breakfix, etc...)
docker_version_dot_escaped="${DOCKER_VERSION//./\\.}" docker_version_dot_escaped="${DOCKER_VERSION//./\\.}"
docker_version_dot_plus_escaped="${docker_version_dot_escaped//+/\\+}" docker_version_dot_plus_escaped="${docker_version_dot_escaped//+/\\+}"
@ -189,75 +175,93 @@ if type docker > /dev/null 2>&1; then
echo "Docker / Moby CLI already installed." echo "Docker / Moby CLI already installed."
else else
if [ "${USE_MOBY}" = "true" ]; then if [ "${USE_MOBY}" = "true" ]; then
apt-get -y install --no-install-recommends moby-cli${cli_version_suffix} moby-buildx buildx=()
if [ "${INSTALL_DOCKER_BUILDX}" = "true" ]; then
buildx=(moby-buildx)
fi
apt-get -y install --no-install-recommends ${cli_package_name}${cli_version_suffix} "${buildx[@]}"
apt-get -y install --no-install-recommends moby-compose || echo "(*) Package moby-compose (Docker Compose v2) not available for OS ${ID} ${VERSION_CODENAME} (${architecture}). Skipping." apt-get -y install --no-install-recommends moby-compose || echo "(*) Package moby-compose (Docker Compose v2) not available for OS ${ID} ${VERSION_CODENAME} (${architecture}). Skipping."
else else
apt-get -y install --no-install-recommends docker-ce-cli${cli_version_suffix} buildx=()
if [ "${INSTALL_DOCKER_BUILDX}" = "true" ]; then
buildx=(docker-buildx-plugin)
fi
apt-get -y install --no-install-recommends ${cli_package_name}${cli_version_suffix} "${buildx[@]}" docker-compose-plugin
buildx_path="/usr/libexec/docker/cli-plugins/docker-buildx"
# Older versions of Docker CE installs buildx as part of the CLI package
if [ "${INSTALL_DOCKER_BUILDX}" = "false" ] && [ -f "${buildx_path}" ]; then
echo "(*) Removing docker-buildx installed from docker-ce-cli since installDockerBuildx is disabled..."
rm -f "${buildx_path}"
fi
fi fi
unset buildx buildx_path
fi fi
# Install Docker Compose if not already installed and is on a supported architecture # If 'docker-compose' command is to be included
if type docker-compose > /dev/null 2>&1; then if [ "${DOCKER_DASH_COMPOSE_VERSION}" != "none" ]; then
echo "Docker Compose already installed." # Install Docker Compose if not already installed and is on a supported architecture
else if type docker-compose > /dev/null 2>&1; then
TARGET_COMPOSE_ARCH="$(uname -m)" echo "Docker Compose already installed."
if [ "${TARGET_COMPOSE_ARCH}" = "amd64" ]; then elif [ "${DOCKER_DASH_COMPOSE_VERSION}" = "v1" ]; then
TARGET_COMPOSE_ARCH="x86_64" TARGET_COMPOSE_ARCH="$(uname -m)"
fi if [ "${TARGET_COMPOSE_ARCH}" = "amd64" ]; then
if [ "${TARGET_COMPOSE_ARCH}" != "x86_64" ]; then TARGET_COMPOSE_ARCH="x86_64"
# Use pip to get a version that runns on this architecture
if ! dpkg -s python3-minimal python3-pip libffi-dev python3-venv > /dev/null 2>&1; then
apt_get_update
apt-get -y install python3-minimal python3-pip libffi-dev python3-venv
fi fi
export PIPX_HOME=/usr/local/pipx if [ "${TARGET_COMPOSE_ARCH}" != "x86_64" ]; then
mkdir -p ${PIPX_HOME} # Use pip to get a version that runs on this architecture
export PIPX_BIN_DIR=/usr/local/bin check_packages python3-minimal python3-pip libffi-dev python3-venv
export PYTHONUSERBASE=/tmp/pip-tmp export PIPX_HOME=/usr/local/pipx
export PIP_CACHE_DIR=/tmp/pip-tmp/cache mkdir -p ${PIPX_HOME}
pipx_bin=pipx export PIPX_BIN_DIR=/usr/local/bin
if ! type pipx > /dev/null 2>&1; then export PYTHONUSERBASE=/tmp/pip-tmp
pip3 install --disable-pip-version-check --no-cache-dir --user pipx export PIP_CACHE_DIR=/tmp/pip-tmp/cache
pipx_bin=/tmp/pip-tmp/bin/pipx pipx_bin=pipx
if ! type pipx > /dev/null 2>&1; then
pip3 install --disable-pip-version-check --no-cache-dir --user pipx
pipx_bin=/tmp/pip-tmp/bin/pipx
fi
${pipx_bin} install --pip-args '--no-cache-dir --force-reinstall' docker-compose
rm -rf /tmp/pip-tmp
else
compose_v1_version="1"
find_version_from_git_tags compose_v1_version "https://github.com/docker/compose" "tags/"
echo "(*) Installing docker-compose ${compose_v1_version}..."
curl -fsSL "https://github.com/docker/compose/releases/download/${compose_v1_version}/docker-compose-Linux-x86_64" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
fi fi
${pipx_bin} install --pip-args '--no-cache-dir --force-reinstall' docker-compose else
rm -rf /tmp/pip-tmp echo "(*) Installing compose-switch as docker-compose..."
else compose_switch_version="latest"
compose_v1_version="1" find_version_from_git_tags compose_switch_version "https://github.com/docker/compose-switch"
find_version_from_git_tags compose_v1_version "https://github.com/docker/compose" "tags/" curl -fsSL "https://github.com/docker/compose-switch/releases/download/v${compose_switch_version}/docker-compose-linux-${architecture}" -o /usr/local/bin/docker-compose
echo "(*) Installing docker-compose ${compose_v1_version}..."
curl -fsSL "https://github.com/docker/compose/releases/download/${compose_v1_version}/docker-compose-Linux-x86_64" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose
# TODO: Verify checksum once available: https://github.com/docker/compose-switch/issues/11
fi fi
fi fi
# Install docker-compose switch if not already installed - https://github.com/docker/compose-switch#manual-installation # Setup a docker group in the event the docker socket's group is not root
current_v1_compose_path="$(which docker-compose)" if ! grep -qE '^docker:' /etc/group; then
target_v1_compose_path="$(dirname "${current_v1_compose_path}")/docker-compose-v1" echo "(*) Creating missing docker group..."
if ! type compose-switch > /dev/null 2>&1; then groupadd --system docker
echo "(*) Installing compose-switch..." fi
compose_switch_version="latest"
find_version_from_git_tags compose_switch_version "https://github.com/docker/compose-switch"
curl -fsSL "https://github.com/docker/compose-switch/releases/download/v${compose_switch_version}/docker-compose-linux-${architecture}" -o /usr/local/bin/compose-switch
chmod +x /usr/local/bin/compose-switch
# TODO: Verify checksum once available: https://github.com/docker/compose-switch/issues/11
# Setup v1 CLI as alternative in addition to compose-switch (which maps to v2) # Remarking this out to restore functionality in Azure VMs. ID 999 is a reserved group ID
mv "${current_v1_compose_path}" "${target_v1_compose_path}" # Ensure docker group gid is 999
update-alternatives --install /usr/local/bin/docker-compose docker-compose /usr/local/bin/compose-switch 99 # if [ "$(getent group docker | cut -d: -f3)" != "999" ]; then
update-alternatives --install /usr/local/bin/docker-compose docker-compose "${target_v1_compose_path}" 1 # echo "(*) Updating docker group gid to 999..."
fi # groupmod -g 999 docker
if [ "${DOCKER_DASH_COMPOSE_VERSION}" = "v1" ]; then # fi
update-alternatives --set docker-compose "${target_v1_compose_path}"
else
update-alternatives --set docker-compose /usr/local/bin/compose-switch usermod -aG docker "${USERNAME}"
fi
# If init file already exists, exit # If init file already exists, exit
if [ -f "/usr/local/share/docker-init.sh" ]; then if [ -f "/usr/local/share/docker-init.sh" ]; then
# Clean up
rm -rf /var/lib/apt/lists/*
exit 0 exit 0
fi fi
echo "docker-init doesnt exist, adding..." echo "docker-init doesn't exist, adding..."
# By default, make the source and target sockets the same # By default, make the source and target sockets the same
if [ "${SOURCE_SOCKET}" != "${TARGET_SOCKET}" ]; then if [ "${SOURCE_SOCKET}" != "${TARGET_SOCKET}" ]; then
@ -269,24 +273,18 @@ fi
if [ "${ENABLE_NONROOT_DOCKER}" = "false" ] || [ "${USERNAME}" = "root" ]; then if [ "${ENABLE_NONROOT_DOCKER}" = "false" ] || [ "${USERNAME}" = "root" ]; then
echo -e '#!/usr/bin/env bash\nexec "$@"' > /usr/local/share/docker-init.sh echo -e '#!/usr/bin/env bash\nexec "$@"' > /usr/local/share/docker-init.sh
chmod +x /usr/local/share/docker-init.sh chmod +x /usr/local/share/docker-init.sh
# Clean up
rm -rf /var/lib/apt/lists/*
exit 0 exit 0
fi fi
# Setup a docker group in the event the docker socket's group is not root
if ! grep -qE '^docker:' /etc/group; then
groupadd --system docker
fi
usermod -aG docker "${USERNAME}"
DOCKER_GID="$(grep -oP '^docker:x:\K[^:]+' /etc/group)" DOCKER_GID="$(grep -oP '^docker:x:\K[^:]+' /etc/group)"
# If enabling non-root access and specified user is found, setup socat and add script # If enabling non-root access and specified user is found, setup socat and add script
chown -h "${USERNAME}":root "${TARGET_SOCKET}" chown -h "${USERNAME}":root "${TARGET_SOCKET}"
if ! dpkg -s socat > /dev/null 2>&1; then check_packages socat
apt_get_update
apt-get -y install socat
fi
tee /usr/local/share/docker-init.sh > /dev/null \ tee /usr/local/share/docker-init.sh > /dev/null \
<< EOF << EOF
#!/usr/bin/env bash #!/usr/bin/env bash
#------------------------------------------------------------------------------------------------------------- #-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved. # Copyright (c) Microsoft Corporation. All rights reserved.
@ -318,8 +316,8 @@ log()
echo -e "\n** \$(date) **" | sudoIf tee -a \${SOCAT_LOG} > /dev/null echo -e "\n** \$(date) **" | sudoIf tee -a \${SOCAT_LOG} > /dev/null
log "Ensuring ${USERNAME} has access to ${SOURCE_SOCKET} via ${TARGET_SOCKET}" log "Ensuring ${USERNAME} has access to ${SOURCE_SOCKET} via ${TARGET_SOCKET}"
# If enabled, try to update the docker group with the right GID. If the group is root, # If enabled, try to update the docker group with the right GID. If the group is root,
# fall back on using socat to forward the docker socket to another unix socket so # fall back on using socat to forward the docker socket to another unix socket so
# that we can set permissions on it without affecting the host. # that we can set permissions on it without affecting the host.
if [ "${ENABLE_NONROOT_DOCKER}" = "true" ] && [ "${SOURCE_SOCKET}" != "${TARGET_SOCKET}" ] && [ "${USERNAME}" != "root" ] && [ "${USERNAME}" != "0" ]; then if [ "${ENABLE_NONROOT_DOCKER}" = "true" ] && [ "${SOURCE_SOCKET}" != "${TARGET_SOCKET}" ] && [ "${USERNAME}" != "root" ] && [ "${USERNAME}" != "0" ]; then
SOCKET_GID=\$(stat -c '%g' ${SOURCE_SOCKET}) SOCKET_GID=\$(stat -c '%g' ${SOURCE_SOCKET})
@ -339,11 +337,15 @@ if [ "${ENABLE_NONROOT_DOCKER}" = "true" ] && [ "${SOURCE_SOCKET}" != "${TARGET_
log "Success" log "Success"
fi fi
# Execute whatever commands were passed in (if any). This allows us # Execute whatever commands were passed in (if any). This allows us
# to set this script to ENTRYPOINT while still executing the default CMD. # to set this script to ENTRYPOINT while still executing the default CMD.
set +e set +e
exec "\$@" exec "\$@"
EOF EOF
chmod +x /usr/local/share/docker-init.sh chmod +x /usr/local/share/docker-init.sh
chown ${USERNAME}:root /usr/local/share/docker-init.sh chown ${USERNAME}:root /usr/local/share/docker-init.sh
# Clean up
rm -rf /var/lib/apt/lists/*
echo "Done!" echo "Done!"

74
src/dotnet/NOTES.md Normal file
View file

@ -0,0 +1,74 @@
## Configuration examples
Installing only the latest .NET SDK version (the default).
``` json
{
"features": {
"ghcr.io/devcontainers/features/dotnet:2": "latest" // or "" or {}
}
```
Installing an additional SDK version. Multiple versions can be specified as comma-separated values.
``` json
{
"features": {
"ghcr.io/devcontainers/features/dotnet:2": {
"additionalVersions": "lts"
}
}
```
Installing specific SDK versions.
``` json
{
"features": {
"ghcr.io/devcontainers/features/dotnet:2": {
"version": "6.0",
"additionalVersions": "7.0, 8.0"
}
}
```
Installing a specific SDK feature band.
``` json
{
"features": {
"ghcr.io/devcontainers/features/dotnet:2": {
"version": "6.0.4xx",
}
}
```
Installing a specific SDK patch version.
``` json
{
"features": {
"ghcr.io/devcontainers/features/dotnet:2": {
"version": "6.0.412",
}
}
```
Installing only the .NET Runtime or the ASP.NET Core Runtime. (The SDK includes all runtimes so this configuration is only useful if you need to run .NET apps without building them from source.)
``` json
{
"features": {
"ghcr.io/devcontainers/features/dotnet:2": {
"version": "none",
"dotnetRuntimeVersions": "latest, lts",
"aspnetCoreRuntimeVersions": "latest, lts",
}
}
```
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.

View file

@ -1,15 +1,13 @@
# Dotnet CLI (dotnet) # Dotnet CLI (dotnet)
Installs the .NET CLI. Provides option of installing sdk or runtime, and option of versions to install. Uses latest version of .NET sdk as defaults to install. This Feature installs the latest .NET SDK, which includes the .NET CLI and the shared runtime. Options are provided to choose a different version or additional versions.
## Example Usage ## Example Usage
```json ```json
"features": { "features": {
"ghcr.io/devcontainers/features/dotnet:1": { "ghcr.io/devcontainers/features/dotnet:2": {}
"version": "latest"
}
} }
``` ```
@ -17,10 +15,91 @@ Installs the .NET CLI. Provides option of installing sdk or runtime, and option
| Options Id | Description | Type | Default Value | | Options Id | Description | Type | Default Value |
|-----|-----|-----|-----| |-----|-----|-----|-----|
| version | Select or enter a dotnet CLI version. (Available versions may vary by Linux distribution.) | string | latest | | version | Select or enter a .NET SDK version. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X.Y' or 'X.Y.Z' for a specific version. | string | latest |
| runtimeOnly | Install just the dotnet runtime if true, and sdk if false. | boolean | - | | additionalVersions | Enter additional .NET SDK versions, separated by commas. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X.Y' or 'X.Y.Z' for a specific version. | string | - |
| installUsingApt | If true, it installs using apt instead of the release URL | boolean | true | | dotnetRuntimeVersions | Enter additional .NET runtime versions, separated by commas. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X.Y' or 'X.Y.Z' for a specific version. | string | - |
| aspNetCoreRuntimeVersions | Enter additional ASP.NET Core runtime versions, separated by commas. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X.Y' or 'X.Y.Z' for a specific version. | string | - |
## Customizations
### VS Code Extensions
- `ms-dotnettools.csharp`
## Configuration examples
Installing only the latest .NET SDK version (the default).
``` json
{
"features": {
"ghcr.io/devcontainers/features/dotnet:2": "latest" // or "" or {}
}
```
Installing an additional SDK version. Multiple versions can be specified as comma-separated values.
``` json
{
"features": {
"ghcr.io/devcontainers/features/dotnet:2": {
"additionalVersions": "lts"
}
}
```
Installing specific SDK versions.
``` json
{
"features": {
"ghcr.io/devcontainers/features/dotnet:2": {
"version": "6.0",
"additionalVersions": "7.0, 8.0"
}
}
```
Installing a specific SDK feature band.
``` json
{
"features": {
"ghcr.io/devcontainers/features/dotnet:2": {
"version": "6.0.4xx",
}
}
```
Installing a specific SDK patch version.
``` json
{
"features": {
"ghcr.io/devcontainers/features/dotnet:2": {
"version": "6.0.412",
}
}
```
Installing only the .NET Runtime or the ASP.NET Core Runtime. (The SDK includes all runtimes so this configuration is only useful if you need to run .NET apps without building them from source.)
``` json
{
"features": {
"ghcr.io/devcontainers/features/dotnet:2": {
"version": "none",
"dotnetRuntimeVersions": "latest, lts",
"aspnetCoreRuntimeVersions": "latest, lts",
}
}
```
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.
--- ---

View file

@ -1,35 +1,44 @@
{ {
"id": "dotnet", "id": "dotnet",
"version": "1.0.6", "version": "2.0.2",
"name": "Dotnet CLI", "name": "Dotnet CLI",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/dotnet", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/dotnet",
"description": "Installs the .NET CLI. Provides option of installing sdk or runtime, and option of versions to install. Uses latest version of .NET sdk as defaults to install.", "description": "This Feature installs the latest .NET SDK, which includes the .NET CLI and the shared runtime. Options are provided to choose a different version or additional versions.",
"options": { "options": {
"version": { "version": {
"type": "string", "type": "string",
"proposals": [ "proposals": [
"latest", "latest",
"6", "lts",
"5", "none",
"3.1" "8.0",
"7.0",
"6.0"
], ],
"default": "latest", "default": "latest",
"description": "Select or enter a dotnet CLI version. (Available versions may vary by Linux distribution.)" "description": "Select or enter a .NET SDK version. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X.Y' or 'X.Y.Z' for a specific version."
}, },
"runtimeOnly": { "additionalVersions": {
"type": "boolean", "type": "string",
"default": false, "default": "",
"description": "Install just the dotnet runtime if true, and sdk if false." "description": "Enter additional .NET SDK versions, separated by commas. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X.Y' or 'X.Y.Z' for a specific version."
}, },
"installUsingApt": { "dotnetRuntimeVersions": {
"type": "boolean", "type": "string",
"default": "true", "default": "",
"description": "If true, it installs using apt instead of the release URL" "description": "Enter additional .NET runtime versions, separated by commas. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X.Y' or 'X.Y.Z' for a specific version."
},
"aspNetCoreRuntimeVersions": {
"type": "string",
"default": "",
"description": "Enter additional ASP.NET Core runtime versions, separated by commas. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X.Y' or 'X.Y.Z' for a specific version."
} }
}, },
"containerEnv": { "containerEnv": {
"DOTNET_ROOT": "/usr/local/dotnet/current", "DOTNET_ROOT": "/usr/share/dotnet",
"PATH": "/usr/local/dotnet/current:${PATH}" "PATH": "$PATH:$DOTNET_ROOT:~/.dotnet/tools",
"DOTNET_RUNNING_IN_CONTAINER": "true",
"DOTNET_USE_POLLING_FILE_WATCHER": "true"
}, },
"customizations": { "customizations": {
"vscode": { "vscode": {
@ -37,5 +46,8 @@
"ms-dotnettools.csharp" "ms-dotnettools.csharp"
] ]
} }
} },
"installsAfter": [
"ghcr.io/devcontainers/features/common-utils"
]
} }

506
src/dotnet/install.sh Executable file → Normal file
View file

@ -4,116 +4,37 @@
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. # Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#------------------------------------------------------------------------------------------------------------- #-------------------------------------------------------------------------------------------------------------
# #
# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/dotnet.md # Docs: https://github.com/devcontainers/features/tree/main/src/dotnet
# Maintainer: The VS Code and Codespaces Teams # Maintainer: The Dev Container spec maintainers
DOTNET_VERSION="${VERSION:-"latest"}"
ADDITIONAL_VERSIONS="${ADDITIONALVERSIONS}"
DOTNET_RUNTIME_VERSIONS="${DOTNETRUNTIMEVERSIONS}"
ASPNETCORE_RUNTIME_VERSIONS="${ASPNETCORERUNTIMEVERSIONS}"
DOTNET_VERSION=${VERSION:-"latest"} set -e
DOTNET_RUNTIME_ONLY=${RUNTIMEONLY:-"false"}
OVERRIDE_DEFAULT_VERSION=${OVERRIDEDEFAULTVERSION:-"true"}
INSTALL_USING_APT=${INSTALLUSINGAPT:-"true"}
USERNAME=${USERNAME:-"automatic"} # Import trim_whitespace and split_csv
UPDATE_RC=${UPDATE_RC:-"true"} source "scripts/string-helpers.sh"
TARGET_DOTNET_ROOT=${TARGET_DOTNET_ROOT:-"/usr/local/dotnet"}
ACCESS_GROUP=${ACCESS_GROUP:-"dotnet"}
MICROSOFT_GPG_KEYS_URI="https://packages.microsoft.com/keys/microsoft.asc" # Import install_sdk and install_runtime
DOTNET_ARCHIVE_ARCHITECTURES="amd64" source "scripts/dotnet-helpers.sh"
DOTNET_ARCHIVE_VERSION_CODENAMES="buster bullseye bionic focal hirsute jammy"
# Feed URI sourced from the official dotnet-install.sh
# https://github.com/dotnet/install-scripts/blob/1b98b94a6f6d81cc4845eb88e0195fac67caa0a6/src/dotnet-install.sh#L1342-L1343
DOTNET_CDN_FEED_URI="https://dotnetcli.azureedge.net"
# Ubuntu 22.04 and on do not ship with libssl1.1, which is required for versions of .NET < 6.0
DOTNET_VERSION_CODENAMES_REQUIRE_OLDER_LIBSSL_1="buster bullseye bionic focal hirsute"
# Comma-separated list of dotnet versions to be installed # Clean up
# alongside DOTNET_VERSION, but not set as default. rm -rf /var/lib/apt/lists/*
ADDITIONAL_VERSIONS=${ADDITIONALVERSIONS:-""}
# Setup STDERR. # Setup STDERR.
err() { err() {
echo "(!) $*" >&2 echo "(!) $*" >&2
} }
# Ensure the appropriate root user is running the script. apt_get_update() {
if [ "$(id -u)" -ne 0 ]; then if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then
err 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' echo "Running apt-get update..."
exit 1 apt-get update -y
fi
# Ensure that login shells get the correct path if the user updated the PATH using ENV.
rm -f /etc/profile.d/00-restore-env.sh
echo "export PATH=${PATH//$(sh -lc 'echo $PATH')/\$PATH}" > /etc/profile.d/00-restore-env.sh
chmod +x /etc/profile.d/00-restore-env.sh
# Determine the appropriate non-root user.
if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then
USERNAME=""
POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)")
for CURRENT_USER in "${POSSIBLE_USERS[@]}"; do
if id -u "${CURRENT_USER}" > /dev/null 2>&1; then
USERNAME="${CURRENT_USER}"
break
fi
done
if [ "${USERNAME}" = "" ]; then
USERNAME=root
fi
elif [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then
USERNAME=root
fi
###################
# Helper Functions
###################
# Cleanup temporary directory and associated files when exiting the script.
cleanup() {
EXIT_CODE=$?
set +e
if [[ -n "${TMP_DIR}" ]]; then
echo "Executing cleanup of tmp files"
rm -Rf "${TMP_DIR}"
fi
exit $EXIT_CODE
}
trap cleanup EXIT
# Get central common setting
get_common_setting() {
if [ "${common_settings_file_loaded}" != "true" ]; then
curl -sfL "https://aka.ms/vscode-dev-containers/script-library/settings.env" 2>/dev/null -o /tmp/vsdc-settings.env || echo "Could not download settings file. Skipping."
common_settings_file_loaded=true
fi
if [ -f "/tmp/vsdc-settings.env" ]; then
local multi_line=""
if [ "$2" = "true" ]; then multi_line="-z"; fi
local result="$(grep ${multi_line} -oP "$1=\"?\K[^\"]+" /tmp/vsdc-settings.env | tr -d '\0')"
if [ ! -z "${result}" ]; then declare -g $1="${result}"; fi
fi
echo "$1=${!1}"
}
# Add dotnet directory to PATH in bashrc/zshrc files if OVERRIDE_DEFAULT_VERSION=true.
updaterc() {
if [ "${UPDATE_RC}" = "true" ]; then
echo "Updating /etc/bash.bashrc and /etc/zsh/zshrc..."
if [[ "$(cat /etc/bash.bashrc)" != *"$1"* ]]; then
echo -e "$1" >> /etc/bash.bashrc
fi
if [ -f "/etc/zsh/zshrc" ] && [[ "$(cat /etc/zsh/zshrc)" != *"$1"* ]]; then
echo -e "$1" >> /etc/zsh/zshrc
fi
fi fi
} }
apt_get_update() # Checks if packages are installed and installs them if not
{
echo "Running apt-get update..."
apt-get update -y
}
# Check if packages are installed and installs them if not.
check_packages() { check_packages() {
if ! dpkg -s "$@" > /dev/null 2>&1; then if ! dpkg -s "$@" > /dev/null 2>&1; then
apt_get_update apt_get_update
@ -121,346 +42,77 @@ check_packages() {
fi fi
} }
# Get appropriate architecture name for .NET binaries for the target OS if [ "$(id -u)" -ne 0 ]; then
get_architecture_name_for_target_os() { err 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
local architecture
architecture="$(uname -m)"
case $architecture in
x86_64) architecture="x64";;
aarch64 | armv8*) architecture="arm64";;
*) err "Architecture ${architecture} unsupported"; exit 1 ;;
esac
echo "${architecture}"
}
# Soft version matching that resolves a version for a given package in the *current apt-cache*
# Return value is stored in first argument (the unprocessed version)
apt_cache_package_and_version_soft_match() {
# Version
local version_variable_name="$1"
local requested_version=${!version_variable_name}
# Package Name
local package_variable_name="$2"
local partial_package_name=${!package_variable_name}
local package_name
# Exit on no match?
local exit_on_no_match="${3:-true}"
local major_minor_version
# Ensure we've exported useful variables
. /etc/os-release
local architecture="$(dpkg --print-architecture)"
major_minor_version="$(echo "${requested_version}" | cut -d "." --field=1,2)"
package_name="$(apt-cache search "${partial_package_name}-[0-9].[0-9]" | awk -F" - " '{print $1}' | grep -m 1 "${partial_package_name}-${major_minor_version}")"
dot_escaped="${requested_version//./\\.}"
dot_plus_escaped="${dot_escaped//+/\\+}"
# Regex needs to handle debian package version number format: https://www.systutorials.com/docs/linux/man/5-deb-version/
version_regex="^(.+:)?${dot_plus_escaped}([\\.\\+ ~:-]|$)"
set +e # Don't exit if finding version fails - handle gracefully
fuzzy_version="$(apt-cache madison ${package_name} | awk -F"|" '{print $2}' | sed -e 's/^[ \t]*//' | grep -E -m 1 "${version_regex}")"
set -e
if [ -z "${fuzzy_version}" ]; then
echo "(!) No full or partial for package \"${partial_package_name}\" (resolved: \"${package_name}\") match found in apt-cache for \"${requested_version}\" on OS ${ID} ${VERSION_CODENAME} (${architecture})."
if $exit_on_no_match; then
echo "Available versions:"
apt-cache madison ${package_name} | awk -F"|" '{print $2}' | grep -oP '^(.+:)?\K.+'
exit 1 # Fail entire script
else
echo "Continuing to fallback method if available"
return 1;
fi
fi
# Globally assign fuzzy_version to this value
# Use this value as the return value of this function
declare -g ${version_variable_name}="=${fuzzy_version}"
echo "${version_variable_name} ${!version_variable_name}"
# Globally assign package to this value
# Use this value as the return value of this function
declare -g ${package_variable_name}="${package_name}"
echo "${package_variable_name} ${!package_variable_name}"
}
# Install .NET CLI using apt-get package installer
install_using_apt_from_microsoft_repo() {
local sdk_or_runtime="$1"
local dotnet_major_minor_version
export DOTNET_PACKAGE="dotnet-${sdk_or_runtime}"
# Install dependencies
check_packages apt-transport-https curl ca-certificates gnupg2 dirmngr
# Import key safely and import Microsoft apt repo
get_common_setting MICROSOFT_GPG_KEYS_URI
curl -sSL ${MICROSOFT_GPG_KEYS_URI} | gpg --dearmor > /usr/share/keyrings/microsoft-archive-keyring.gpg
echo "deb [arch=${architecture} signed-by=/usr/share/keyrings/microsoft-archive-keyring.gpg] https://packages.microsoft.com/repos/microsoft-${ID}-${VERSION_CODENAME}-prod ${VERSION_CODENAME} main" > /etc/apt/sources.list.d/microsoft.list
apt-get update -y
if [ "${DOTNET_VERSION}" = "latest" ] || [ "${DOTNET_VERSION}" = "lts" ]; then
DOTNET_VERSION=""
DOTNET_PACKAGE="${DOTNET_PACKAGE}-6.0"
else
# Sets DOTNET_VERSION and DOTNET_PACKAGE if matches found.
apt_cache_package_and_version_soft_match DOTNET_VERSION DOTNET_PACKAGE false
if [ "$?" != 0 ]; then
echo "Failed to find requested version."
return 1
fi
if [[ $(dotnet --version) == *"${DOTNET_VERSION}"* ]] ; then
echo "Dotnet version ${DOTNET_VERSION} is already installed"
return 1
fi
fi
echo "Installing '${DOTNET_PACKAGE}${DOTNET_VERSION}'..."
apt-get install -yq ${DOTNET_PACKAGE}${DOTNET_VERSION}
if [ "$?" != 0 ]; then
echo "Failed to complete apt install of ${DOTNET_PACKAGE}${DOTNET_VERSION}"
return 1
fi
}
install_using_default_apt_repo() {
DOTNET_PACKAGE="dotnet6"
apt_get_update
if [[ "${DOTNET_VERSION}" = "latest" ]] || [[ "${DOTNET_VERSION}" = "lts" ]] || [[ ${DOTNET_VERSION} = "6"* ]]; then
if ! (apt-get install -yq ${DOTNET_PACKAGE}); then
echo "Failed to install 'dotnet6' package from default apt repo."
return 1
fi
else
echo "The provided dotnet version is not distributed in this distro's default apt repo."
return 1
fi
}
# Find and extract .NET binary download details based on user-requested version
# args:
# sdk_or_runtime $1
# exports:
# DOTNET_DOWNLOAD_URL
# DOTNET_DOWNLOAD_HASH
# DOTNET_DOWNLOAD_NAME
get_full_version_details() {
local sdk_or_runtime="$1"
local VERSION="$2"
local architecture
local dotnet_channel_version
local dotnet_releases_url
local dotnet_releases_json
local dotnet_latest_version
local dotnet_download_details
export DOTNET_DOWNLOAD_URL
export DOTNET_DOWNLOAD_HASH
export DOTNET_DOWNLOAD_NAME
# Set architecture variable to current user's architecture (x64 or ARM64).
architecture="$(get_architecture_name_for_target_os)"
# Set VERSION to empty string to ensure jq includes all .NET versions in reverse sort below
if [ "${VERSION}" = "latest" ]; then
VERSION=""
fi
dotnet_patchless_version="$(echo "${VERSION}" | cut -d "." --field=1,2)"
set +e
dotnet_channel_version="$(curl -s "${DOTNET_CDN_FEED_URI}/dotnet/release-metadata/releases-index.json" | jq -r --arg channel_version "${dotnet_patchless_version}" '[."releases-index"[]] | sort_by(."channel-version") | reverse | map( select(."channel-version" | startswith($channel_version))) | first | ."channel-version"')"
set -e
# Construct the releases URL using the official channel-version if one was found. Otherwise make a best-effort using the user input.
if [ -n "${dotnet_channel_version}" ] && [ "${dotnet_channel_version}" != "null" ]; then
dotnet_releases_url="${DOTNET_CDN_FEED_URI}/dotnet/release-metadata/${dotnet_channel_version}/releases.json"
else
dotnet_releases_url="${DOTNET_CDN_FEED_URI}/dotnet/release-metadata/${dotnet_patchless_version}/releases.json"
fi
set +e
dotnet_releases_json="$(curl -s "${dotnet_releases_url}")"
set -e
if [ -n "${dotnet_releases_json}" ] && [[ ! "${dotnet_releases_json}" = *"Error"* ]]; then
dotnet_latest_version="$(echo "${dotnet_releases_json}" | jq -r --arg sdk_or_runtime "${sdk_or_runtime}" '."latest-\($sdk_or_runtime)"')"
# If user-specified version has 2 or more dots, use it as is. Otherwise use latest version.
if [ "$(echo "${VERSION}" | grep -o "\." | wc -l)" -lt "2" ]; then
VERSION="${dotnet_latest_version}"
fi
dotnet_download_details="$(echo "${dotnet_releases_json}" | jq -r --arg sdk_or_runtime "${sdk_or_runtime}" --arg dotnet_version "${VERSION}" --arg arch "${architecture}" '.releases[]."\($sdk_or_runtime)" | select(.version==$dotnet_version) | .files[] | select(.name=="dotnet-\($sdk_or_runtime)-linux-\($arch).tar.gz")')"
if [ -n "${dotnet_download_details}" ]; then
echo "Found .NET binary version ${VERSION}"
DOTNET_DOWNLOAD_URL="$(echo "${dotnet_download_details}" | jq -r '.url')"
DOTNET_DOWNLOAD_HASH="$(echo "${dotnet_download_details}" | jq -r '.hash')"
DOTNET_DOWNLOAD_NAME="$(echo "${dotnet_download_details}" | jq -r '.name')"
else
err "Unable to find .NET binary for version ${VERSION}"
exit 1
fi
else
err "Unable to find .NET release details for version ${VERSION} at ${dotnet_releases_url}"
exit 1
fi
}
# Install .NET CLI using the .NET releases url
install_using_dotnet_releases_url() {
local sdk_or_runtime="$1"
local VERSION="$2"
# Check listed package dependecies and install them if they are not already installed.
# NOTE: icu-devtools is a small package with similar dependecies to .NET.
# It will install the appropriate dependencies based on the OS:
# - libgcc-s1 OR libgcc1 depending on OS
# - the latest libicuXX depending on OS (eg libicu57 for stretch)
# - also installs libc6 and libstdc++6 which are required by .NET
check_packages curl ca-certificates tar jq icu-devtools libgssapi-krb5-2 zlib1g
# Starting with Ubuntu 22.04 (jammy), libssl1.1 does not ship with the OS anymore.
if [[ "${DOTNET_VERSION_CODENAMES_REQUIRE_OLDER_LIBSSL_1}" = *"${VERSION_CODENAME}"* ]]; then
check_packages libssl1.1
else
check_packages libssl3.0
fi
get_full_version_details "${sdk_or_runtime}" "${VERSION}"
DOTNET_INSTALL_PATH="${TARGET_DOTNET_ROOT}/${VERSION}"
if [ -d "${DOTNET_INSTALL_PATH}" ]; then
echo "(!) Dotnet version ${VERSION} already exists."
exit 1
fi
# exports DOTNET_DOWNLOAD_URL, DOTNET_DOWNLOAD_HASH, DOTNET_DOWNLOAD_NAME
echo "DOWNLOAD LINK: ${DOTNET_DOWNLOAD_URL}"
# Setup the access group and add the user to it.
umask 0002
if ! cat /etc/group | grep -e "^${ACCESS_GROUP}:" > /dev/null 2>&1; then
groupadd -r "${ACCESS_GROUP}"
fi
usermod -a -G "${ACCESS_GROUP}" "${USERNAME}"
# Download the .NET binaries.
echo "DOWNLOADING BINARY..."
TMP_DIR="/tmp/dotnetinstall"
mkdir -p "${TMP_DIR}"
curl -sSL "${DOTNET_DOWNLOAD_URL}" -o "${TMP_DIR}/${DOTNET_DOWNLOAD_NAME}"
# Get checksum from .NET CLI blob storage using the runtime version and
# run validation (sha512sum) of checksum against the expected checksum hash.
echo "VERIFY CHECKSUM"
cd "${TMP_DIR}"
echo "${DOTNET_DOWNLOAD_HASH} *${DOTNET_DOWNLOAD_NAME}" | sha512sum -c -
# Extract binaries and add to path.
mkdir -p "${DOTNET_INSTALL_PATH}"
echo "Extract Binary to ${DOTNET_INSTALL_PATH}"
tar -xzf "${TMP_DIR}/${DOTNET_DOWNLOAD_NAME}" -C "${DOTNET_INSTALL_PATH}" --strip-components=1
CURRENT_DIR="${TARGET_DOTNET_ROOT}/current"
if [[ ! -d "${CURRENT_DIR}" ]]; then
ln -s "${DOTNET_INSTALL_PATH}" "${CURRENT_DIR}"
fi
# Give write permissions to the user.
chown -R "${USERNAME}:${USERNAME}" "${CURRENT_DIR}"
chmod g+r+w+s "${CURRENT_DIR}"
chmod -R g+r+w "${CURRENT_DIR}"
if [[ "${OVERRIDE_DEFAULT_VERSION}" = "true" ]]; then
if [[ $(ls -l ${CURRENT_DIR}) != *"-> ${DOTNET_INSTALL_PATH}"* ]] ; then
rm "${CURRENT_DIR}"
ln -s "${DOTNET_INSTALL_PATH}" "${CURRENT_DIR}"
fi
fi
updaterc "if [[ \"\${PATH}\" != *\"${CURRENT_DIR}\"* ]]; then export PATH=${CURRENT_DIR}:\${PATH}; fi"
}
###########################
# Start .NET installation
###########################
export DEBIAN_FRONTEND=noninteractive
. /etc/os-release
architecture="$(dpkg --print-architecture)"
# Dotnet 3.1 and 5 are not supported on Ubuntu 22.04 (jammy)+,
# due to lack of libssl3.0 support.
# See: https://github.com/microsoft/vscode-dev-containers/issues/1458#issuecomment-1135077775
# NOTE: This will only guard against installation of the dotnet versions we propose via 'features'.
# The user can attempt to install any other version at their own risk.
if [[ "${DOTNET_VERSION}" = "3"* ]] || [[ "${DOTNET_VERSION}" = "5"* ]]; then
if [[ ! "${DOTNET_VERSION_CODENAMES_REQUIRE_OLDER_LIBSSL_1}" = *"${VERSION_CODENAME}"* ]]; then
err "Dotnet ${DOTNET_VERSION} is not supported on Ubuntu ${VERSION_CODENAME} due to a change in the 'libssl' dependency across distributions.\n Please upgrade your version of dotnet, or downgrade your OS version."
exit 1
fi
fi
# Determine if the user wants to download .NET Runtime only, or .NET SDK & Runtime
# and set the appropriate variables.
if [ "${DOTNET_RUNTIME_ONLY}" = "true" ]; then
DOTNET_SDK_OR_RUNTIME="runtime"
elif [ "${DOTNET_RUNTIME_ONLY}" = "false" ]; then
DOTNET_SDK_OR_RUNTIME="sdk"
else
err "Expected true for installing dotnet Runtime only or false for installing SDK and Runtime. Received ${DOTNET_RUNTIME_ONLY}."
exit 1 exit 1
fi fi
# Install the .NET CLI # For our own convenience, combine DOTNET_VERSION and ADDITIONAL_VERSIONS into a single 'versions' array
echo "(*) Installing .NET CLI..." versions=()
CHANGE_OWNERSHIP="false" # The version can be set to 'none' for runtime-only installations, then the array will just remain empty
if [[ "${DOTNET_ARCHIVE_ARCHITECTURES}" = *"${architecture}"* ]] && [[ "${DOTNET_ARCHIVE_VERSION_CODENAMES}" = *"${VERSION_CODENAME}"* ]] && [[ "${INSTALL_USING_APT}" = "true" ]]; then # Ensure there are no leading or trailing spaces that can break regex pattern matching
echo "Detected ${VERSION_CODENAME} on ${architecture}. Attempting to install dotnet from apt" if [ "$DOTNET_VERSION" != "none" ]; then
versions+=("$(trim_whitespace "$DOTNET_VERSION")")
for additional_version in $(split_csv "$ADDITIONAL_VERSIONS"); do
versions+=("$additional_version")
done
fi
install_using_default_apt_repo || install_using_apt_from_microsoft_repo "${DOTNET_SDK_OR_RUNTIME}" dotnetRuntimeVersions=()
if [ "$?" != 0 ]; then for dotnetRuntimeVersion in $(split_csv "$DOTNET_RUNTIME_VERSIONS"); do
echo "Could not install requested version from apt on current distribution." dotnetRuntimeVersions+=("$dotnetRuntimeVersion")
done
aspNetCoreRuntimeVersions=()
for aspNetCoreRuntimeVersion in $(split_csv "$ASPNETCORE_RUNTIME_VERSIONS"); do
aspNetCoreRuntimeVersions+=("$aspNetCoreRuntimeVersion")
done
# Fail fast in case of bad input to avoid unneccesary work
# v1 of the .NET feature allowed specifying only a major version 'X' like '3'
# v2 removed this ability
# - because install-dotnet.sh does not support it directly
# - because the previous behavior installed an old version like '3.0.103', not the newest version '3.1.426', which was counterintuitive
for version in "${versions[@]}"; do
if [[ "$version" =~ ^[0-9]+$ ]]; then
err "Unsupported .NET SDK version '${version}'. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X.Y' or 'X.Y.Z' for a specific version."
exit 1 exit 1
fi fi
else done
if [[ "${INSTALL_USING_APT}" = "false" ]]; then
echo "Installing dotnet from releases url" for version in "${dotnetRuntimeVersions[@]}"; do
else if [[ "$version" =~ ^[0-9]+$ ]]; then
echo "Attempting to install dotnet from releases url" err "Unsupported .NET Runtime version '${version}'. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X.Y' or 'X.Y.Z' for a specific version."
exit 1
fi fi
install_using_dotnet_releases_url "${DOTNET_SDK_OR_RUNTIME}" "${DOTNET_VERSION}" done
CHANGE_OWNERSHIP="true"
fi
# Additional dotnet versions to be installed but not be set as default. for version in "${aspNetCoreRuntimeVersions[@]}"; do
if [ ! -z "${ADDITIONAL_VERSIONS}" ]; then if [[ "$version" =~ ^[0-9]+$ ]]; then
OLDIFS=$IFS err "Unsupported ASP.NET Core Runtime version '${version}'. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X.Y' or 'X.Y.Z' for a specific version."
IFS="," exit 1
read -a additional_versions <<< "$ADDITIONAL_VERSIONS"
for version in "${additional_versions[@]}"; do
OVERRIDE_DEFAULT_VERSION="false"
install_using_dotnet_releases_url "${DOTNET_SDK_OR_RUNTIME}" "${version}"
done
IFS=$OLDIFS
fi
if [ "${CHANGE_OWNERSHIP}" = "true" ]; then
if ! cat /etc/group | grep -e "^dotnet:" > /dev/null 2>&1; then
groupadd -r dotnet
fi fi
usermod -a -G dotnet "${USERNAME}" done
chown -R "${USERNAME}:dotnet" "${TARGET_DOTNET_ROOT}" # Install .NET versions and dependencies
chmod -R g+r+w "${TARGET_DOTNET_ROOT}" # icu-devtools includes dependencies for .NET
find "${TARGET_DOTNET_ROOT}" -type d -print0 | xargs -n 1 -0 chmod g+s check_packages wget ca-certificates icu-devtools
fi
for version in "${versions[@]}"; do
install_sdk "$version"
done
for version in "${dotnetRuntimeVersions[@]}"; do
install_runtime "dotnet" "$version"
done
for version in "${aspNetCoreRuntimeVersions[@]}"; do
install_runtime "aspnetcore" "$version"
done
# Clean up
rm -rf /var/lib/apt/lists/*
rm -rf scripts
echo "Done!" echo "Done!"

View file

@ -0,0 +1,119 @@
#!/bin/bash
#-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------
#
# Docs: https://github.com/devcontainers/features/tree/main/src/dotnet
# Maintainer: The Dev Container spec maintainers
DOTNET_SCRIPTS=$(dirname "${BASH_SOURCE[0]}")
DOTNET_INSTALL_SCRIPT="$DOTNET_SCRIPTS/vendor/dotnet-install.sh"
DOTNET_INSTALL_DIR='/usr/share/dotnet'
# Prints the latest dotnet version in the specified channel
# Usage: fetch_latest_version_in_channel <channel> [<runtime>]
# Example: fetch_latest_version_in_channel "LTS"
# Example: fetch_latest_version_in_channel "6.0" "dotnet"
# Example: fetch_latest_version_in_channel "6.0" "aspnetcore"
fetch_latest_version_in_channel() {
local channel="$1"
local runtime="$2"
if [ "$runtime" = "dotnet" ]; then
wget -qO- "https://dotnetcli.azureedge.net/dotnet/Runtime/$channel/latest.version"
elif [ "$runtime" = "aspnetcore" ]; then
wget -qO- "https://dotnetcli.azureedge.net/dotnet/aspnetcore/Runtime/$channel/latest.version"
else
wget -qO- "https://dotnetcli.azureedge.net/dotnet/Sdk/$channel/latest.version"
fi
}
# Prints the latest dotnet version
# Usage: fetch_latest_version [<runtime>]
# Example: fetch_latest_version
# Example: fetch_latest_version "dotnet"
# Example: fetch_latest_version "aspnetcore"
fetch_latest_version() {
local runtime="$1"
local sts_version
local lts_version
sts_version=$(fetch_latest_version_in_channel "STS" "$runtime")
lts_version=$(fetch_latest_version_in_channel "LTS" "$runtime")
if [[ "$sts_version" > "$lts_version" ]]; then
echo "$sts_version"
else
echo "$lts_version"
fi
}
# Installs a version of the .NET SDK
# Usage: install_sdk <version>
install_sdk() {
local inputVersion="$1"
local version=""
local channel=""
if [[ "$inputVersion" == "latest" ]]; then
# Fetch the latest version manually, because dotnet-install.sh does not support it directly
version=$(fetch_latest_version)
elif [[ "$inputVersion" == "lts" ]]; then
# When user input is 'lts'
# Then version=latest, channel=LTS
version="latest"
channel="LTS"
elif [[ "$inputVersion" =~ ^[0-9]+\.[0-9]+$ ]]; then
# When user input is form 'A.B' like '3.1'
# Then version=latest, channel=3.1
version="latest"
channel="$inputVersion"
elif [[ "$inputVersion" =~ ^[0-9]+\.[0-9]+\.[0-9]xx$ ]]; then
# When user input is form 'A.B.Cxx' like '6.0.4xx'
# Then version=latest, channel=6.0.4xx
version="latest"
channel="$inputVersion"
else
# Assume version is an exact version string like '6.0.413' or '8.0.100-rc.2.23425.18'
version="$inputVersion"
fi
# Currently this script does not make it possible to qualify the version, 'GA' is always implied
echo "Executing $DOTNET_INSTALL_SCRIPT --version $version --channel $channel --install-dir $DOTNET_INSTALL_DIR --no-path"
"$DOTNET_INSTALL_SCRIPT" \
--version "$version" \
--channel "$channel" \
--install-dir "$DOTNET_INSTALL_DIR" \
--no-path
}
# Installs a version of the .NET Runtime
# Usage: install_runtime <runtime> <version>
install_runtime() {
local runtime="$1"
local inputVersion="$2"
local version=""
local channel=""
if [[ "$inputVersion" == "latest" ]]; then
# Fetch the latest version manually, because dotnet-install.sh does not support it directly
version=$(fetch_latest_version "$runtime")
elif [[ "$inputVersion" == "lts" ]]; then
# When user input is 'lts'
# Then version=latest, channel=LTS
version="latest"
channel="LTS"
elif [[ "$inputVersion" =~ ^[0-9]+\.[0-9]+$ ]]; then
# When user input is form 'A.B' like '3.1'
# Then version=latest, channel=3.1
version="latest"
channel="$inputVersion"
else
# Assume version is an exact version string like '6.0.21' or '8.0.0-preview.7.23375.6'
version="$inputVersion"
fi
echo "Executing $DOTNET_INSTALL_SCRIPT --runtime $runtime --version $version --channel $channel --install-dir $DOTNET_INSTALL_DIR --no-path"
"$DOTNET_INSTALL_SCRIPT" \
--runtime "$runtime" \
--version "$version" \
--channel "$channel" \
--install-dir "$DOTNET_INSTALL_DIR" \
--no-path
}

View file

@ -0,0 +1,16 @@
#!/bin/bash
#-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------
#
# Docs: https://github.com/devcontainers/features/tree/main/src/dotnet
# Maintainer: The Dev Container spec maintainers
#
# Run this script to replace dotnet-install.sh with the latest and greatest available version
#
DOTNET_SCRIPTS=$(dirname "${BASH_SOURCE[0]}")
DOTNET_INSTALL_SCRIPT="$DOTNET_SCRIPTS/vendor/dotnet-install.sh"
wget https://dot.net/v1/dotnet-install.sh -O "$DOTNET_INSTALL_SCRIPT"
chmod +x "$DOTNET_INSTALL_SCRIPT"

View file

@ -0,0 +1,42 @@
#!/bin/bash
#-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------
#
# Docs: https://github.com/devcontainers/features/tree/main/src/dotnet
# Maintainer: The Dev Container spec maintainers
# Removes leading and trailing whitespace from an input string
# Usage: trim_whitespace <text>
trim_whitespace() {
text="$1"
# Remove leading spaces
while [ "${text:0:1}" == " " ]; do
text="${text:1}"
done
# Remove trailing spaces
while [ "${text: -1}" == " " ]; do
text="${text:0:-1}"
done
echo "$text"
}
# Splits comma-separated values into an array while ignoring empty entries
# Usage: split_csv <comma-separated-values>
split_csv() {
local -a values=()
while IFS="," read -ra entries; do
for entry in "${entries[@]}"; do
entry="$(trim_whitespace "$entry")"
if [ -n "$entry" ]; then
values+=("$entry")
fi
done
done <<< "$1"
echo "${values[@]}"
}

27
src/dotnet/scripts/vendor/README.md vendored Normal file
View file

@ -0,0 +1,27 @@
### **IMPORTANT NOTE**
Scripts in this directory are sourced externally and not maintained by the Dev Container spec maintainers. Do not make changes directly as they might be overwritten at any moment.
## dotnet-install.sh
`dotnet-install.sh` is a copy of <https://dot.net/v1/dotnet-install.sh>. ([Script reference](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script))
Quick options reminder for `dotnet-install.sh`:
- `--version`: `"latest"` (default) or an exact version in the form A.B.C like `"6.0.413"`
- `--channel`: `"LTS"` (default), `"STS"`, a two-part version in the form A.B like `"6.0"` or three-part form A.B.Cxx like `"6.0.1xx"`
- `--quality`: `"daily"`, `"preview"` or `"GA"`
- The channel option is only used when version is 'latest' because an exact version overrides the channel option
- The quality option is only used when channel is 'A.B' or 'A.B.Cxx' because it can't be used with STS or LTS
Examples
```
dotnet-install.sh [--version latest] [--channel LTS]
dotnet-install.sh [--version latest] --channel STS
dotnet-install.sh [--version latest] --channel 6.0 [--quality GA]
dotnet-install.sh [--version latest] --channel 6.0.4xx [--quality GA]
dotnet-install.sh [--version latest] --channel 8.0 --quality preview
dotnet-install.sh [--version latest] --channel 8.0 --quality daily
dotnet-install.sh --version 6.0.413
```

1835
src/dotnet/scripts/vendor/dotnet-install.sh vendored Executable file

File diff suppressed because it is too large Load diff

7
src/git-lfs/NOTES.md Normal file
View file

@ -0,0 +1,7 @@
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.

View file

@ -7,9 +7,7 @@ Installs Git Large File Support (Git LFS) along with needed dependencies. Useful
```json ```json
"features": { "features": {
"ghcr.io/devcontainers/features/git-lfs:1": { "ghcr.io/devcontainers/features/git-lfs:1": {}
"version": "latest"
}
} }
``` ```
@ -18,9 +16,17 @@ Installs Git Large File Support (Git LFS) along with needed dependencies. Useful
| Options Id | Description | Type | Default Value | | Options Id | Description | Type | Default Value |
|-----|-----|-----|-----| |-----|-----|-----|-----|
| version | Select version of Git LFS to install | string | latest | | version | Select version of Git LFS to install | string | latest |
| autoPull | Automatically pull LFS files when creating the container. When false, running 'git lfs pull' in the container will have the same effect. | boolean | true |
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.
--- ---
_Note: This file was auto-generated from the [devcontainer-feature.json](https://github.com/devcontainers/features/blob/main/src/git-lfs/devcontainer-feature.json). Add additional notes to a `NOTES.md`._ _Note: This file was auto-generated from the [devcontainer-feature.json](https://github.com/devcontainers/features/blob/main/src/git-lfs/devcontainer-feature.json). Add additional notes to a `NOTES.md`._

View file

@ -1,18 +1,27 @@
{ {
"id": "git-lfs", "id": "git-lfs",
"version": "1.0.2", "version": "1.1.1",
"name": "Git Large File Support (LFS)", "name": "Git Large File Support (LFS)",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/git-lfs", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/git-lfs",
"description": "Installs Git Large File Support (Git LFS) along with needed dependencies. Useful for base Dockerfiles that often are missing required install dependencies like git and curl.", "description": "Installs Git Large File Support (Git LFS) along with needed dependencies. Useful for base Dockerfiles that often are missing required install dependencies like git and curl.",
"options": { "options": {
"version": { "version": {
"type": "string", "type": "string",
"enum": [ "proposals": [
"latest", "latest",
"none" "none"
], ],
"default": "latest", "default": "latest",
"description": "Select version of Git LFS to install" "description": "Select version of Git LFS to install"
},
"autoPull": {
"type": "boolean",
"default": true,
"description": "Automatically pull LFS files when creating the container. When false, running 'git lfs pull' in the container will have the same effect."
} }
} },
"postCreateCommand": "/usr/local/share/pull-git-lfs-artifacts.sh",
"installsAfter": [
"ghcr.io/devcontainers/features/common-utils"
]
} }

View file

@ -8,37 +8,27 @@
# Maintainer: The VS Code and Codespaces Teams # Maintainer: The VS Code and Codespaces Teams
GIT_LFS_VERSION=${VERSION:-"latest"} GIT_LFS_VERSION=${VERSION:-"latest"}
AUTO_PULL=${AUTOPULL:="true"}
GIT_LFS_ARCHIVE_GPG_KEY_URI="https://packagecloud.io/github/git-lfs/gpgkey" GIT_LFS_ARCHIVE_GPG_KEY_URI="https://packagecloud.io/github/git-lfs/gpgkey"
GIT_LFS_ARCHIVE_ARCHITECTURES="amd64 arm64" GIT_LFS_ARCHIVE_ARCHITECTURES="amd64 arm64"
GIT_LFS_ARCHIVE_VERSION_CODENAMES="stretch buster bullseye bionic focal jammy" GIT_LFS_ARCHIVE_VERSION_CODENAMES="stretch buster bullseye bionic focal jammy"
GIT_LFS_CHECKSUM_GPG_KEYS="0x88ace9b29196305ba9947552f1ba225c0223b187 0x86cd3297749375bcf8206715f54fe648088335a9 0xaa3b3450295830d2de6db90caba67be5a5795889" GIT_LFS_CHECKSUM_GPG_KEYS="0x88ace9b29196305ba9947552f1ba225c0223b187 0x86cd3297749375bcf8206715f54fe648088335a9 0xaa3b3450295830d2de6db90caba67be5a5795889"
GPG_KEY_SERVERS="keyserver hkp://keyserver.ubuntu.com:80 GPG_KEY_SERVERS="keyserver hkp://keyserver.ubuntu.com
keyserver hkp://keyserver.ubuntu.com:80
keyserver hkps://keys.openpgp.org keyserver hkps://keys.openpgp.org
keyserver hkp://keyserver.pgp.com" keyserver hkp://keyserver.pgp.com"
set -e set -e
# Clean up
rm -rf /var/lib/apt/lists/*
if [ "$(id -u)" -ne 0 ]; then if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1 exit 1
fi fi
# Get central common setting
get_common_setting() {
if [ "${common_settings_file_loaded}" != "true" ]; then
curl -sfL "https://aka.ms/vscode-dev-containers/script-library/settings.env" 2>/dev/null -o /tmp/vsdc-settings.env || echo "Could not download settings file. Skipping."
common_settings_file_loaded=true
fi
if [ -f "/tmp/vsdc-settings.env" ]; then
local multi_line=""
if [ "$2" = "true" ]; then multi_line="-z"; fi
local result="$(grep ${multi_line} -oP "$1=\"?\K[^\"]+" /tmp/vsdc-settings.env | tr -d '\0')"
if [ ! -z "${result}" ]; then declare -g $1="${result}"; fi
fi
echo "$1=${!1}"
}
# Figure out correct version of a three part version number is not passed # Figure out correct version of a three part version number is not passed
find_version_from_git_tags() { find_version_from_git_tags() {
local variable_name=$1 local variable_name=$1
@ -75,11 +65,9 @@ find_version_from_git_tags() {
# Import the specified key in a variable name passed in as # Import the specified key in a variable name passed in as
receive_gpg_keys() { receive_gpg_keys() {
get_common_setting $1
local keys=${!1} local keys=${!1}
get_common_setting GPG_KEY_SERVERS true
# Use a temporary locaiton for gpg keys to avoid polluting image # Use a temporary location for gpg keys to avoid polluting image
export GNUPGHOME="/tmp/tmp-gnupg" export GNUPGHOME="/tmp/tmp-gnupg"
mkdir -p ${GNUPGHOME} mkdir -p ${GNUPGHOME}
chmod 700 ${GNUPGHOME} chmod 700 ${GNUPGHOME}
@ -107,8 +95,10 @@ receive_gpg_keys() {
apt_get_update() apt_get_update()
{ {
echo "Running apt-get update..." if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then
apt-get update -y echo "Running apt-get update..."
apt-get update -y
fi
} }
# Checks if packages are installed and installs them if not # Checks if packages are installed and installs them if not
@ -128,7 +118,6 @@ install_using_apt() {
version_suffix="" version_suffix=""
fi fi
# Install # Install
get_common_setting GIT_LFS_ARCHIVE_GPG_KEY_URI
curl -sSL "${GIT_LFS_ARCHIVE_GPG_KEY_URI}" | gpg --dearmor > /usr/share/keyrings/gitlfs-archive-keyring.gpg curl -sSL "${GIT_LFS_ARCHIVE_GPG_KEY_URI}" | gpg --dearmor > /usr/share/keyrings/gitlfs-archive-keyring.gpg
echo -e "deb [arch=${architecture} signed-by=/usr/share/keyrings/gitlfs-archive-keyring.gpg] https://packagecloud.io/github/git-lfs/${ID} ${VERSION_CODENAME} main\ndeb-src [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/gitlfs-archive-keyring.gpg] https://packagecloud.io/github/git-lfs/${ID} ${VERSION_CODENAME} main" > /etc/apt/sources.list.d/git-lfs.list echo -e "deb [arch=${architecture} signed-by=/usr/share/keyrings/gitlfs-archive-keyring.gpg] https://packagecloud.io/github/git-lfs/${ID} ${VERSION_CODENAME} main\ndeb-src [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/gitlfs-archive-keyring.gpg] https://packagecloud.io/github/git-lfs/${ID} ${VERSION_CODENAME} main" > /etc/apt/sources.list.d/git-lfs.list
@ -178,8 +167,7 @@ export DEBIAN_FRONTEND=noninteractive
. /etc/os-release . /etc/os-release
check_packages curl ca-certificates gnupg2 dirmngr apt-transport-https check_packages curl ca-certificates gnupg2 dirmngr apt-transport-https
if ! type git > /dev/null 2>&1; then if ! type git > /dev/null 2>&1; then
apt_get_update check_packages git
apt-get -y install --no-install-recommends git
fi fi
if [ "${ID}" = "debian" ]; then if [ "${ID}" = "debian" ]; then
check_packages debian-archive-keyring check_packages debian-archive-keyring
@ -199,4 +187,38 @@ if [ "${use_github}" = "true" ]; then
install_using_github install_using_github
fi fi
echo "Done!" # --- Generate a 'pull-git-lfs-artifacts.sh' script to be executed by the 'postCreateCommand' lifecycle hook
PULL_GIT_LFS_SCRIPT_PATH="/usr/local/share/pull-git-lfs-artifacts.sh"
tee "$PULL_GIT_LFS_SCRIPT_PATH" > /dev/null \
<< EOF
#!/bin/sh
set -e
AUTO_PULL=${AUTO_PULL}
EOF
tee -a "$PULL_GIT_LFS_SCRIPT_PATH" > /dev/null \
<< 'EOF'
echo "Fetching git lfs artifacts..."
if [ "${AUTO_PULL}" != "true" ]; then
echo "(!) Skipping 'git lfs pull' because 'autoPull' is not set to 'true'"
exit 0
fi
# Check if repo is a git lfs repo.
if ! git lfs ls-files > /dev/null 2>&1; then
echo "(!) Skipping automatic 'git lfs pull' because no git lfs files were detected"
exit 0
fi
git lfs pull
EOF
chmod 755 "$PULL_GIT_LFS_SCRIPT_PATH"
# Clean up
rm -rf /var/lib/apt/lists/*
echo "Done!"

7
src/git/NOTES.md Normal file
View file

@ -0,0 +1,7 @@
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.

View file

@ -7,9 +7,7 @@ Install an up-to-date version of Git, built from source as needed. Useful for wh
```json ```json
"features": { "features": {
"ghcr.io/devcontainers/features/git:1": { "ghcr.io/devcontainers/features/git:1": {}
"version": "latest"
}
} }
``` ```
@ -22,6 +20,13 @@ Install an up-to-date version of Git, built from source as needed. Useful for wh
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.
--- ---
_Note: This file was auto-generated from the [devcontainer-feature.json](https://github.com/devcontainers/features/blob/main/src/git/devcontainer-feature.json). Add additional notes to a `NOTES.md`._ _Note: This file was auto-generated from the [devcontainer-feature.json](https://github.com/devcontainers/features/blob/main/src/git/devcontainer-feature.json). Add additional notes to a `NOTES.md`._

View file

@ -1,6 +1,6 @@
{ {
"id": "git", "id": "git",
"version": "1.0.3", "version": "1.1.6",
"name": "Git (from source)", "name": "Git (from source)",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/git", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/git",
"description": "Install an up-to-date version of Git, built from source as needed. Useful for when you want the latest and greatest features. Auto-detects latest stable version and installs needed dependencies.", "description": "Install an up-to-date version of Git, built from source as needed. Useful for when you want the latest and greatest features. Auto-detects latest stable version and installs needed dependencies.",
@ -19,5 +19,8 @@
"default": true, "default": true,
"description": "Install from PPA if available" "description": "Install from PPA if available"
} }
} },
"installsAfter": [
"ghcr.io/devcontainers/features/common-utils"
]
} }

View file

@ -11,44 +11,31 @@ GIT_VERSION=${VERSION} # 'system' checks the base image first, else installs 'la
USE_PPA_IF_AVAILABLE=${PPA} USE_PPA_IF_AVAILABLE=${PPA}
GIT_CORE_PPA_ARCHIVE_GPG_KEY=E1DD270288B4E6030699E45FA1715D88E1DF1F24 GIT_CORE_PPA_ARCHIVE_GPG_KEY=E1DD270288B4E6030699E45FA1715D88E1DF1F24
GPG_KEY_SERVERS="keyserver hkp://keyserver.ubuntu.com:80 GPG_KEY_SERVERS="keyserver hkp://keyserver.ubuntu.com
keyserver hkp://keyserver.ubuntu.com:80
keyserver hkps://keys.openpgp.org keyserver hkps://keys.openpgp.org
keyserver hkp://keyserver.pgp.com" keyserver hkp://keyserver.pgp.com"
set -e set -e
# Clean up
rm -rf /var/lib/apt/lists/*
if [ "$(id -u)" -ne 0 ]; then if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1 exit 1
fi fi
# Get central common setting
get_common_setting() {
if [ "${common_settings_file_loaded}" != "true" ]; then
curl -sfL "https://aka.ms/vscode-dev-containers/script-library/settings.env" 2>/dev/null -o /tmp/vsdc-settings.env || echo "Could not download settings file. Skipping."
common_settings_file_loaded=true
fi
if [ -f "/tmp/vsdc-settings.env" ]; then
local multi_line=""
if [ "$2" = "true" ]; then multi_line="-z"; fi
local result="$(grep ${multi_line} -oP "$1=\"?\K[^\"]+" /tmp/vsdc-settings.env | tr -d '\0')"
if [ ! -z "${result}" ]; then declare -g $1="${result}"; fi
fi
echo "$1=${!1}"
}
# Import the specified key in a variable name passed in as # Import the specified key in a variable name passed in as
receive_gpg_keys() { receive_gpg_keys() {
get_common_setting $1
local keys=${!1} local keys=${!1}
get_common_setting GPG_KEY_SERVERS true
local keyring_args="" local keyring_args=""
if [ ! -z "$2" ]; then if [ ! -z "$2" ]; then
mkdir -p "$(dirname \"$2\")" mkdir -p "$(dirname \"$2\")"
keyring_args="--no-default-keyring --keyring $2" keyring_args="--no-default-keyring --keyring $2"
fi fi
# Use a temporary locaiton for gpg keys to avoid polluting image # Use a temporary location for gpg keys to avoid polluting image
export GNUPGHOME="/tmp/tmp-gnupg" export GNUPGHOME="/tmp/tmp-gnupg"
mkdir -p ${GNUPGHOME} mkdir -p ${GNUPGHOME}
chmod 700 ${GNUPGHOME} chmod 700 ${GNUPGHOME}
@ -76,8 +63,10 @@ receive_gpg_keys() {
apt_get_update() apt_get_update()
{ {
echo "Running apt-get update..." if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then
apt-get update -y echo "Running apt-get update..."
apt-get update -y
fi
} }
# Checks if packages are installed and installs them if not # Checks if packages are installed and installs them if not
@ -96,12 +85,16 @@ export DEBIAN_FRONTEND=noninteractive
# If the os provided version is "good enough", just install that. # If the os provided version is "good enough", just install that.
if [ ${GIT_VERSION} = "os-provided" ] || [ ${GIT_VERSION} = "system" ]; then if [ ${GIT_VERSION} = "os-provided" ] || [ ${GIT_VERSION} = "system" ]; then
if type git > /dev/null 2>&1; then if type git > /dev/null 2>&1; then
echo "Detected existing system install: $(git version)" echo "Detected existing system install: $(git version)"
exit 0 # Clean up
rm -rf /var/lib/apt/lists/*
exit 0
fi fi
echo "Installing git from OS apt repository" echo "Installing git from OS apt repository"
check_packages git check_packages git
# Clean up
rm -rf /var/lib/apt/lists/*
exit 0 exit 0
fi fi
@ -114,6 +107,7 @@ if ([ "${GIT_VERSION}" = "latest" ] || [ "${GIT_VERSION}" = "lts" ] || [ "${GIT_
apt-get update apt-get update
apt-get -y install --no-install-recommends git apt-get -y install --no-install-recommends git
rm -rf "/tmp/tmp-gnupg" rm -rf "/tmp/tmp-gnupg"
rm -rf /var/lib/apt/lists/*
exit 0 exit 0
fi fi
@ -137,10 +131,21 @@ if [ "$(echo "${GIT_VERSION}" | grep -o '\.' | wc -l)" != "2" ]; then
fi fi
fi fi
check_packages libpcre2-dev
if [ "${VERSION_CODENAME}" = "focal" ] || [ "${VERSION_CODENAME}" = "bullseye" ]; then
check_packages libpcre2-posix2
elif [ "${VERSION_CODENAME}" = "bionic" ] || [ "${VERSION_CODENAME}" = "buster" ]; then
check_packages libpcre2-posix0
else
check_packages libpcre2-posix3
fi
echo "Downloading source for ${GIT_VERSION}..." echo "Downloading source for ${GIT_VERSION}..."
curl -sL https://github.com/git/git/archive/v${GIT_VERSION}.tar.gz | tar -xzC /tmp 2>&1 curl -sL https://github.com/git/git/archive/v${GIT_VERSION}.tar.gz | tar -xzC /tmp 2>&1
echo "Building..." echo "Building..."
cd /tmp/git-${GIT_VERSION} cd /tmp/git-${GIT_VERSION}
make -s prefix=/usr/local all && make -s prefix=/usr/local install 2>&1 make -s USE_LIBPCRE=YesPlease prefix=/usr/local sysconfdir=/etc all && make -s USE_LIBPCRE=YesPlease prefix=/usr/local sysconfdir=/etc install 2>&1
rm -rf /tmp/git-${GIT_VERSION} rm -rf /tmp/git-${GIT_VERSION}
rm -rf /var/lib/apt/lists/*
echo "Done!" echo "Done!"

7
src/github-cli/NOTES.md Normal file
View file

@ -0,0 +1,7 @@
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.

View file

@ -7,9 +7,7 @@ Installs the GitHub CLI. Auto-detects latest version and installs needed depende
```json ```json
"features": { "features": {
"ghcr.io/devcontainers/features/github-cli:1": { "ghcr.io/devcontainers/features/github-cli:1": {}
"version": "latest"
}
} }
``` ```
@ -22,6 +20,13 @@ Installs the GitHub CLI. Auto-detects latest version and installs needed depende
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.
--- ---
_Note: This file was auto-generated from the [devcontainer-feature.json](https://github.com/devcontainers/features/blob/main/src/github-cli/devcontainer-feature.json). Add additional notes to a `NOTES.md`._ _Note: This file was auto-generated from the [devcontainer-feature.json](https://github.com/devcontainers/features/blob/main/src/github-cli/devcontainer-feature.json). Add additional notes to a `NOTES.md`._

View file

@ -1,6 +1,6 @@
{ {
"id": "github-cli", "id": "github-cli",
"version": "1.0.4", "version": "1.0.11",
"name": "GitHub CLI", "name": "GitHub CLI",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/github-cli", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/github-cli",
"description": "Installs the GitHub CLI. Auto-detects latest version and installs needed dependencies.", "description": "Installs the GitHub CLI. Auto-detects latest version and installs needed dependencies.",
@ -18,6 +18,10 @@
"type": "boolean", "type": "boolean",
"default": true "default": true
} }
} },
"installsAfter": [
"ghcr.io/devcontainers/features/common-utils",
"ghcr.io/devcontainers/features/git"
]
} }

View file

@ -11,39 +11,31 @@ CLI_VERSION=${VERSION:-"latest"}
INSTALL_DIRECTLY_FROM_GITHUB_RELEASE=${INSTALLDIRECTLYFROMGITHUBRELEASE:-"true"} INSTALL_DIRECTLY_FROM_GITHUB_RELEASE=${INSTALLDIRECTLYFROMGITHUBRELEASE:-"true"}
GITHUB_CLI_ARCHIVE_GPG_KEY=23F3D4EA75716059 GITHUB_CLI_ARCHIVE_GPG_KEY=23F3D4EA75716059
GPG_KEY_SERVERS="keyserver hkp://keyserver.ubuntu.com:80 GPG_KEY_SERVERS="keyserver hkp://keyserver.ubuntu.com
keyserver hkp://keyserver.ubuntu.com:80
keyserver hkps://keys.openpgp.org keyserver hkps://keys.openpgp.org
keyserver hkp://keyserver.pgp.com" keyserver hkp://keyserver.pgp.com"
set -e set -e
# Clean up
rm -rf /var/lib/apt/lists/*
if [ "$(id -u)" -ne 0 ]; then if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1 exit 1
fi fi
# Get central common setting
get_common_setting() {
if [ "${common_settings_file_loaded}" != "true" ]; then
curl -sfL "https://aka.ms/vscode-dev-containers/script-library/settings.env" 2>/dev/null -o /tmp/vsdc-settings.env || echo "Could not download settings file. Skipping."
common_settings_file_loaded=true
fi
if [ -f "/tmp/vsdc-settings.env" ]; then
local multi_line=""
if [ "$2" = "true" ]; then multi_line="-z"; fi
local result="$(grep ${multi_line} -oP "$1=\"?\K[^\"]+" /tmp/vsdc-settings.env | tr -d '\0')"
if [ ! -z "${result}" ]; then declare -g $1="${result}"; fi
fi
echo "$1=${!1}"
}
# Import the specified key in a variable name passed in as # Import the specified key in a variable name passed in as
receive_gpg_keys() { receive_gpg_keys() {
get_common_setting $1
local keys=${!1} local keys=${!1}
get_common_setting GPG_KEY_SERVERS true local keyring_args=""
if [ ! -z "$2" ]; then
keyring_args="--no-default-keyring --keyring $2"
fi
# Use a temporary locaiton for gpg keys to avoid polluting image # Use a temporary location for gpg keys to avoid polluting image
export GNUPGHOME="/tmp/tmp-gnupg" export GNUPGHOME="/tmp/tmp-gnupg"
mkdir -p ${GNUPGHOME} mkdir -p ${GNUPGHOME}
chmod 700 ${GNUPGHOME} chmod 700 ${GNUPGHOME}
@ -55,7 +47,7 @@ receive_gpg_keys() {
until [ "${gpg_ok}" = "true" ] || [ "${retry_count}" -eq "5" ]; until [ "${gpg_ok}" = "true" ] || [ "${retry_count}" -eq "5" ];
do do
echo "(*) Downloading GPG key..." echo "(*) Downloading GPG key..."
( echo "${keys}" | xargs -n 1 gpg --recv-keys) 2>&1 && gpg_ok="true" ( echo "${keys}" | xargs -n 1 gpg -q ${keyring_args} --recv-keys) 2>&1 && gpg_ok="true"
if [ "${gpg_ok}" != "true" ]; then if [ "${gpg_ok}" != "true" ]; then
echo "(*) Failed getting key, retring in 10s..." echo "(*) Failed getting key, retring in 10s..."
(( retry_count++ )) (( retry_count++ ))
@ -69,6 +61,22 @@ receive_gpg_keys() {
fi fi
} }
apt_get_update()
{
if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then
echo "Running apt-get update..."
apt-get update -y
fi
}
# Checks if packages are installed and installs them if not
check_packages() {
if ! dpkg -s "$@" > /dev/null 2>&1; then
apt_get_update
apt-get -y install --no-install-recommends "$@"
fi
}
# Figure out correct version of a three part version number is not passed # Figure out correct version of a three part version number is not passed
find_version_from_git_tags() { find_version_from_git_tags() {
local variable_name=$1 local variable_name=$1
@ -103,89 +111,46 @@ find_version_from_git_tags() {
echo "${variable_name}=${!variable_name}" echo "${variable_name}=${!variable_name}"
} }
# Import the specified key in a variable name passed in as # Use semver logic to decrement a version number then look for the closest match
receive_gpg_keys() { find_prev_version_from_git_tags() {
get_common_setting $1
local keys=${!1}
get_common_setting GPG_KEY_SERVERS true
local keyring_args=""
if [ ! -z "$2" ]; then
keyring_args="--no-default-keyring --keyring $2"
fi
# Use a temporary locaiton for gpg keys to avoid polluting image
export GNUPGHOME="/tmp/tmp-gnupg"
mkdir -p ${GNUPGHOME}
chmod 700 ${GNUPGHOME}
echo -e "disable-ipv6\n${GPG_KEY_SERVERS}" > ${GNUPGHOME}/dirmngr.conf
# GPG key download sometimes fails for some reason and retrying fixes it.
local retry_count=0
local gpg_ok="false"
set +e
until [ "${gpg_ok}" = "true" ] || [ "${retry_count}" -eq "5" ];
do
echo "(*) Downloading GPG key..."
( echo "${keys}" | xargs -n 1 gpg -q ${keyring_args} --recv-keys) 2>&1 && gpg_ok="true"
if [ "${gpg_ok}" != "true" ]; then
echo "(*) Failed getting key, retring in 10s..."
(( retry_count++ ))
sleep 10s
fi
done
set -e
if [ "${gpg_ok}" = "false" ]; then
echo "(!) Failed to get gpg key."
exit 1
fi
}
apt_get_update()
{
echo "Running apt-get update..."
apt-get update -y
}
# Checks if packages are installed and installs them if not
check_packages() {
if ! dpkg -s "$@" > /dev/null 2>&1; then
apt_get_update
apt-get -y install --no-install-recommends "$@"
fi
}
find_version_from_git_tags() {
local variable_name=$1 local variable_name=$1
local requested_version=${!variable_name} local current_version=${!variable_name}
if [ "${requested_version}" = "none" ]; then return; fi
local repository=$2 local repository=$2
# Normally a "v" is used before the version number, but support alternate cases
local prefix=${3:-"tags/v"} local prefix=${3:-"tags/v"}
# Some repositories use "_" instead of "." for version number part separation, support that
local separator=${4:-"."} local separator=${4:-"."}
local last_part_optional=${5:-"false"} # Some tools release versions that omit the last digit (e.g. go)
if [ "$(echo "${requested_version}" | grep -o "." | wc -l)" != "2" ]; then local last_part_optional=${5:-"false"}
local escaped_separator=${separator//./\\.} # Some repositories may have tags that include a suffix (e.g. actions/node-versions)
local last_part local version_suffix_regex=$6
if [ "${last_part_optional}" = "true" ]; then # Try one break fix version number less if we get a failure. Use "set +e" since "set -e" can cause failures in valid scenarios.
last_part="(${escaped_separator}[0-9]+)?" set +e
else major="$(echo "${current_version}" | grep -oE '^[0-9]+' || echo '')"
last_part="${escaped_separator}[0-9]+" minor="$(echo "${current_version}" | grep -oP '^[0-9]+\.\K[0-9]+' || echo '')"
fi breakfix="$(echo "${current_version}" | grep -oP '^[0-9]+\.[0-9]+\.\K[0-9]+' 2>/dev/null || echo '')"
local regex="${prefix}\\K[0-9]+${escaped_separator}[0-9]+${last_part}$"
local version_list="$(git ls-remote --tags ${repository} | grep -oP "${regex}" | tr -d ' ' | tr "${separator}" "." | sort -rV)"
if [ "${requested_version}" = "latest" ] || [ "${requested_version}" = "current" ] || [ "${requested_version}" = "lts" ]; then
declare -g ${variable_name}="$(echo "${version_list}" | head -n 1)"
else
set +e
declare -g ${variable_name}="$(echo "${version_list}" | grep -E -m 1 "^${requested_version//./\\.}([\\.\\s]|$)")"
set -e
fi
fi
if [ -z "${!variable_name}" ] || ! echo "${version_list}" | grep "^${!variable_name//./\\.}$" > /dev/null 2>&1; then
echo -e "Invalid ${variable_name} value: ${requested_version}\nValid values:\n${version_list}" >&2
exit 1
fi
echo "${variable_name}=${!variable_name}"
}
if [ "${minor}" = "0" ] && [ "${breakfix}" = "0" ]; then
((major=major-1))
declare -g ${variable_name}="${major}"
# Look for latest version from previous major release
find_version_from_git_tags "${variable_name}" "${repository}" "${prefix}" "${separator}" "${last_part_optional}"
# Handle situations like Go's odd version pattern where "0" releases omit the last part
elif [ "${breakfix}" = "" ] || [ "${breakfix}" = "0" ]; then
((minor=minor-1))
declare -g ${variable_name}="${major}.${minor}"
# Look for latest version from previous minor release
find_version_from_git_tags "${variable_name}" "${repository}" "${prefix}" "${separator}" "${last_part_optional}"
else
((breakfix=breakfix-1))
if [ "${breakfix}" = "0" ] && [ "${last_part_optional}" = "true" ]; then
declare -g ${variable_name}="${major}.${minor}"
else
declare -g ${variable_name}="${major}.${minor}.${breakfix}"
fi
fi
set -e
}
# Fall back on direct download if no apt package exists # Fall back on direct download if no apt package exists
# Fetches .deb file to be installed with dpkg # Fetches .deb file to be installed with dpkg
@ -199,6 +164,15 @@ install_deb_using_github() {
mkdir -p /tmp/ghcli mkdir -p /tmp/ghcli
pushd /tmp/ghcli pushd /tmp/ghcli
wget https://github.com/cli/cli/releases/download/v${CLI_VERSION}/${cli_filename} wget https://github.com/cli/cli/releases/download/v${CLI_VERSION}/${cli_filename}
exit_code=$?
set -e
if [ "$exit_code" != "0" ]; then
# Handle situation where git tags are ahead of what was is available to actually download
echo "(!) github-cli version ${CLI_VERSION} failed to download. Attempting to fall back one version to retry..."
find_prev_version_from_git_tags CLI_VERSION https://github.com/cli/cli
wget https://github.com/cli/cli/releases/download/v${CLI_VERSION}/${cli_filename}
fi
dpkg -i /tmp/ghcli/${cli_filename} dpkg -i /tmp/ghcli/${cli_filename}
popd popd
rm -rf /tmp/ghcli rm -rf /tmp/ghcli
@ -209,8 +183,7 @@ export DEBIAN_FRONTEND=noninteractive
# Install curl, apt-transport-https, curl, gpg, or dirmngr, git if missing # Install curl, apt-transport-https, curl, gpg, or dirmngr, git if missing
check_packages curl ca-certificates apt-transport-https dirmngr gnupg2 check_packages curl ca-certificates apt-transport-https dirmngr gnupg2
if ! type git > /dev/null 2>&1; then if ! type git > /dev/null 2>&1; then
apt_get_update check_packages git
apt-get -y install --no-install-recommends git
fi fi
# Soft version matching # Soft version matching
@ -236,3 +209,6 @@ else
rm -rf "/tmp/gh/gnupg" rm -rf "/tmp/gh/gnupg"
echo "Done!" echo "Done!"
fi fi
# Clean up
rm -rf /var/lib/apt/lists/*

7
src/go/NOTES.md Normal file
View file

@ -0,0 +1,7 @@
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.

View file

@ -7,9 +7,7 @@ Installs Go and common Go utilities. Auto-detects latest version and installs ne
```json ```json
"features": { "features": {
"ghcr.io/devcontainers/features/go:1": { "ghcr.io/devcontainers/features/go:1": {}
"version": "latest"
}
} }
``` ```
@ -18,7 +16,21 @@ Installs Go and common Go utilities. Auto-detects latest version and installs ne
| Options Id | Description | Type | Default Value | | Options Id | Description | Type | Default Value |
|-----|-----|-----|-----| |-----|-----|-----|-----|
| version | Select or enter a Go version to install | string | latest | | version | Select or enter a Go version to install | string | latest |
| golangciLintVersion | Version of golangci-lint to install | string | latest |
## Customizations
### VS Code Extensions
- `golang.Go`
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.
--- ---

View file

@ -1,6 +1,6 @@
{ {
"id": "go", "id": "go",
"version": "1.0.7", "version": "1.2.2",
"name": "Go", "name": "Go",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/go", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/go",
"description": "Installs Go and common Go utilities. Auto-detects latest version and installs needed dependencies.", "description": "Installs Go and common Go utilities. Auto-detects latest version and installs needed dependencies.",
@ -10,11 +10,16 @@
"proposals": [ "proposals": [
"latest", "latest",
"none", "none",
"1.19", "1.21",
"1.18" "1.20"
], ],
"default": "latest", "default": "latest",
"description": "Select or enter a Go version to install" "description": "Select or enter a Go version to install"
},
"golangciLintVersion": {
"type": "string",
"default": "latest",
"description": "Version of golangci-lint to install"
} }
}, },
"init": true, "init": true,
@ -35,5 +40,8 @@
], ],
"securityOpt": [ "securityOpt": [
"seccomp=unconfined" "seccomp=unconfined"
],
"installsAfter": [
"ghcr.io/devcontainers/features/common-utils"
] ]
} }

View file

@ -7,18 +7,22 @@
# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/go.md # Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/go.md
# Maintainer: The VS Code and Codespaces Teams # Maintainer: The VS Code and Codespaces Teams
TARGET_GO_VERSION=${VERSION:-"latest"} TARGET_GO_VERSION="${VERSION:-"latest"}"
GOLANGCILINT_VERSION="${GOLANGCILINTVERSION:-"latest"}"
TARGET_GOROOT=${TARGET_GOROOT:-"/usr/local/go"} TARGET_GOROOT="${TARGET_GOROOT:-"/usr/local/go"}"
TARGET_GOPATH=${TARGET_GOPATH:-"/go"} TARGET_GOPATH="${TARGET_GOPATH:-"/go"}"
USERNAME=${USERNAME:-"automatic"} USERNAME="${USERNAME:-"${_REMOTE_USER:-"automatic"}"}"
INSTALL_GO_TOOLS=${INSTALL_GO_TOOLS:-"true"} INSTALL_GO_TOOLS="${INSTALL_GO_TOOLS:-"true"}"
# https://www.google.com/linuxrepositories/ # https://www.google.com/linuxrepositories/
GO_GPG_KEY_URI="https://dl.google.com/linux/linux_signing_key.pub" GO_GPG_KEY_URI="https://dl.google.com/linux/linux_signing_key.pub"
set -e set -e
# Clean up
rm -rf /var/lib/apt/lists/*
if [ "$(id -u)" -ne 0 ]; then if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1 exit 1
@ -80,25 +84,12 @@ find_version_from_git_tags() {
echo "${variable_name}=${!variable_name}" echo "${variable_name}=${!variable_name}"
} }
# Get central common setting
get_common_setting() {
if [ "${common_settings_file_loaded}" != "true" ]; then
curl -sfL "https://aka.ms/vscode-dev-containers/script-library/settings.env" 2>/dev/null -o /tmp/vsdc-settings.env || echo "Could not download settings file. Skipping."
common_settings_file_loaded=true
fi
if [ -f "/tmp/vsdc-settings.env" ]; then
local multi_line=""
if [ "$2" = "true" ]; then multi_line="-z"; fi
local result="$(grep ${multi_line} -oP "$1=\"?\K[^\"]+" /tmp/vsdc-settings.env | tr -d '\0')"
if [ ! -z "${result}" ]; then declare -g $1="${result}"; fi
fi
echo "$1=${!1}"
}
apt_get_update() apt_get_update()
{ {
echo "Running apt-get update..." if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then
apt-get update -y echo "Running apt-get update..."
apt-get update -y
fi
} }
# Checks if packages are installed and installs them if not # Checks if packages are installed and installs them if not
@ -114,8 +105,7 @@ export DEBIAN_FRONTEND=noninteractive
# Install curl, tar, git, other dependencies if missing # Install curl, tar, git, other dependencies if missing
check_packages curl ca-certificates gnupg2 tar g++ gcc libc6-dev make pkg-config check_packages curl ca-certificates gnupg2 tar g++ gcc libc6-dev make pkg-config
if ! type git > /dev/null 2>&1; then if ! type git > /dev/null 2>&1; then
apt_get_update check_packages git
apt-get -y install --no-install-recommends git
fi fi
# Get closest match for version number specified # Get closest match for version number specified
@ -137,12 +127,12 @@ if ! cat /etc/group | grep -e "^golang:" > /dev/null 2>&1; then
fi fi
usermod -a -G golang "${USERNAME}" usermod -a -G golang "${USERNAME}"
mkdir -p "${TARGET_GOROOT}" "${TARGET_GOPATH}" mkdir -p "${TARGET_GOROOT}" "${TARGET_GOPATH}"
if [ "${TARGET_GO_VERSION}" != "none" ] && ! type go > /dev/null 2>&1; then
# Use a temporary locaiton for gpg keys to avoid polluting image if [[ "${TARGET_GO_VERSION}" != "none" ]] && [[ "$(go version)" != *"${TARGET_GO_VERSION}"* ]]; then
# Use a temporary location for gpg keys to avoid polluting image
export GNUPGHOME="/tmp/tmp-gnupg" export GNUPGHOME="/tmp/tmp-gnupg"
mkdir -p ${GNUPGHOME} mkdir -p ${GNUPGHOME}
chmod 700 ${GNUPGHOME} chmod 700 ${GNUPGHOME}
get_common_setting GO_GPG_KEY_URI
curl -sSL -o /tmp/tmp-gnupg/golang_key "${GO_GPG_KEY_URI}" curl -sSL -o /tmp/tmp-gnupg/golang_key "${GO_GPG_KEY_URI}"
gpg -q --import /tmp/tmp-gnupg/golang_key gpg -q --import /tmp/tmp-gnupg/golang_key
echo "Downloading Go ${TARGET_GO_VERSION}..." echo "Downloading Go ${TARGET_GO_VERSION}..."
@ -181,20 +171,22 @@ if [ "${TARGET_GO_VERSION}" != "none" ] && ! type go > /dev/null 2>&1; then
tar -xzf /tmp/go.tar.gz -C "${TARGET_GOROOT}" --strip-components=1 tar -xzf /tmp/go.tar.gz -C "${TARGET_GOROOT}" --strip-components=1
rm -rf /tmp/go.tar.gz /tmp/go.tar.gz.asc /tmp/tmp-gnupg rm -rf /tmp/go.tar.gz /tmp/go.tar.gz.asc /tmp/tmp-gnupg
else else
echo "Go already installed. Skipping." echo "(!) Go is already installed with version ${TARGET_GO_VERSION}. Skipping."
fi fi
# Install Go tools that are isImportant && !replacedByGopls based on # Install Go tools that are isImportant && !replacedByGopls based on
# https://github.com/golang/vscode-go/blob/v0.31.1/src/goToolsInformation.ts # https://github.com/golang/vscode-go/blob/v0.38.0/src/goToolsInformation.ts
GO_TOOLS="\ GO_TOOLS="\
golang.org/x/tools/gopls@latest \ golang.org/x/tools/gopls@latest \
honnef.co/go/tools/cmd/staticcheck@latest \ honnef.co/go/tools/cmd/staticcheck@latest \
golang.org/x/lint/golint@latest \ golang.org/x/lint/golint@latest \
github.com/mgechev/revive@latest \ github.com/mgechev/revive@latest \
github.com/uudashr/gopkgs/v2/cmd/gopkgs@latest \
github.com/ramya-rao-a/go-outline@latest \
github.com/go-delve/delve/cmd/dlv@latest \ github.com/go-delve/delve/cmd/dlv@latest \
github.com/golangci/golangci-lint/cmd/golangci-lint@latest" github.com/fatih/gomodifytags@latest \
github.com/haya14busa/goplay/cmd/goplay@latest \
github.com/cweill/gotests/gotests@latest \
github.com/josharian/impl@latest"
if [ "${INSTALL_GO_TOOLS}" = "true" ]; then if [ "${INSTALL_GO_TOOLS}" = "true" ]; then
echo "Installing common Go tools..." echo "Installing common Go tools..."
export PATH=${TARGET_GOROOT}/bin:${PATH} export PATH=${TARGET_GOROOT}/bin:${PATH}
@ -214,9 +206,21 @@ if [ "${INSTALL_GO_TOOLS}" = "true" ]; then
(echo "${GO_TOOLS}" | xargs -n 1 go ${go_install_command} -v )2>&1 | tee -a /usr/local/etc/vscode-dev-containers/go.log (echo "${GO_TOOLS}" | xargs -n 1 go ${go_install_command} -v )2>&1 | tee -a /usr/local/etc/vscode-dev-containers/go.log
# Move Go tools into path and clean up # Move Go tools into path and clean up
mv /tmp/gotools/bin/* ${TARGET_GOPATH}/bin/ if [ -d /tmp/gotools/bin ]; then
mv /tmp/gotools/bin/* ${TARGET_GOPATH}/bin/
rm -rf /tmp/gotools
fi
rm -rf /tmp/gotools # Install golangci-lint from precompiled binares
if [ "$GOLANGCILINT_VERSION" = "latest" ] || [ "$GOLANGCILINT_VERSION" = "" ]; then
echo "Installing golangci-lint latest..."
curl -fsSL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | \
sh -s -- -b "${TARGET_GOPATH}/bin"
else
echo "Installing golangci-lint ${GOLANGCILINT_VERSION}..."
curl -fsSL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | \
sh -s -- -b "${TARGET_GOPATH}/bin" "v${GOLANGCILINT_VERSION}"
fi
fi fi
@ -225,4 +229,7 @@ chmod -R g+r+w "${TARGET_GOROOT}" "${TARGET_GOPATH}"
find "${TARGET_GOROOT}" -type d -print0 | xargs -n 1 -0 chmod g+s find "${TARGET_GOROOT}" -type d -print0 | xargs -n 1 -0 chmod g+s
find "${TARGET_GOPATH}" -type d -print0 | xargs -n 1 -0 chmod g+s find "${TARGET_GOPATH}" -type d -print0 | xargs -n 1 -0 chmod g+s
# Clean up
rm -rf /var/lib/apt/lists/*
echo "Done!" echo "Done!"

7
src/hugo/NOTES.md Normal file
View file

@ -0,0 +1,7 @@
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.

View file

@ -7,9 +7,7 @@
```json ```json
"features": { "features": {
"ghcr.io/devcontainers/features/hugo:1": { "ghcr.io/devcontainers/features/hugo:1": {}
"version": "latest"
}
} }
``` ```
@ -18,9 +16,17 @@
| Options Id | Description | Type | Default Value | | Options Id | Description | Type | Default Value |
|-----|-----|-----|-----| |-----|-----|-----|-----|
| version | Select or enter a version. | string | latest | | version | Select or enter a version. | string | latest |
| extended | Install Hugo extended for SASS/SCSS changes | boolean | false |
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.
--- ---
_Note: This file was auto-generated from the [devcontainer-feature.json](https://github.com/devcontainers/features/blob/main/src/hugo/devcontainer-feature.json). Add additional notes to a `NOTES.md`._ _Note: This file was auto-generated from the [devcontainer-feature.json](https://github.com/devcontainers/features/blob/main/src/hugo/devcontainer-feature.json). Add additional notes to a `NOTES.md`._

View file

@ -1,6 +1,6 @@
{ {
"id": "hugo", "id": "hugo",
"version": "1.0.4", "version": "1.1.2",
"name": "Hugo", "name": "Hugo",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/hugo", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/hugo",
"options": { "options": {
@ -11,10 +11,18 @@
], ],
"default": "latest", "default": "latest",
"description": "Select or enter a version." "description": "Select or enter a version."
},
"extended": {
"type": "boolean",
"default": false,
"description": "Install Hugo extended for SASS/SCSS changes"
} }
}, },
"containerEnv": { "containerEnv": {
"HUGO_DIR": "/usr/local/hugo", "HUGO_DIR": "/usr/local/hugo",
"PATH": "/usr/local/hugo/bin:${PATH}" "PATH": "/usr/local/hugo/bin:${PATH}"
} },
"installsAfter": [
"ghcr.io/devcontainers/features/common-utils"
]
} }

View file

@ -7,15 +7,18 @@
# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/hugo.md # Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/hugo.md
# Maintainer: The VS Code and Codespaces Teams # Maintainer: The VS Code and Codespaces Teams
VERSION=${VERSION:-"latest"} VERSION="${VERSION:-"latest"}"
USERNAME=${USERNAME:-"automatic"} USERNAME="${USERNAME:-"${_REMOTE_USER:-"automatic"}"}"
UPDATE_RC=${UPDATE_RC:-"true"} UPDATE_RC="${UPDATE_RC:-"true"}"
HUGO_DIR=${HUGO_DIR:-"/usr/local/hugo"} HUGO_DIR="${HUGO_DIR:-"/usr/local/hugo"}"
set -e set -e
# Clean up
rm -rf /var/lib/apt/lists/*
if [ "$(id -u)" -ne 0 ]; then if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1 exit 1
@ -63,8 +66,10 @@ updaterc() {
apt_get_update() apt_get_update()
{ {
echo "Running apt-get update..." if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then
apt-get update -y echo "Running apt-get update..."
apt-get update -y
fi
} }
# Checks if packages are installed and installs them if not # Checks if packages are installed and installs them if not
@ -101,7 +106,14 @@ if ! hugo version &> /dev/null ; then
arch="64bit" arch="64bit"
fi fi
hugo_filename="hugo_${VERSION}_Linux-${arch}.tar.gz" # Install extended version of hugo if desired
if [ "${EXTENDED}" = "true" ]; then
extended="extended_"
else
extended=""
fi
hugo_filename="hugo_${extended}${VERSION}_Linux-${arch}.tar.gz"
curl -fsSLO --compressed "https://github.com/gohugoio/hugo/releases/download/v${VERSION}/${hugo_filename}" curl -fsSLO --compressed "https://github.com/gohugoio/hugo/releases/download/v${VERSION}/${hugo_filename}"
tar -xzf "$hugo_filename" -C "$installation_dir" tar -xzf "$hugo_filename" -C "$installation_dir"
@ -114,4 +126,7 @@ if ! hugo version &> /dev/null ; then
find "${HUGO_DIR}" -type d -print0 | xargs -n 1 -0 chmod g+s find "${HUGO_DIR}" -type d -print0 | xargs -n 1 -0 chmod g+s
fi fi
# Clean up
rm -rf /var/lib/apt/lists/*
echo "Done!" echo "Done!"

View file

@ -1,3 +1,10 @@
## License ## License
For the Java Feature from this repository, see [NOTICE.txt](https://github.com/devcontainers/features/tree/main/src/java/NOTICE.txt) for licensing information on JDK distributions. For the Java Feature from this repository, see [NOTICE.txt](https://github.com/devcontainers/features/tree/main/src/java/NOTICE.txt) for licensing information on JDK distributions.
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.

View file

@ -7,9 +7,7 @@ Installs Java, SDKMAN! (if not installed), and needed dependencies.
```json ```json
"features": { "features": {
"ghcr.io/devcontainers/features/java:1": { "ghcr.io/devcontainers/features/java:1": {}
"version": "latest"
}
} }
``` ```
@ -19,14 +17,31 @@ Installs Java, SDKMAN! (if not installed), and needed dependencies.
|-----|-----|-----|-----| |-----|-----|-----|-----|
| version | Select or enter a Java version to install | string | latest | | version | Select or enter a Java version to install | string | latest |
| jdkDistro | Select or enter a JDK distribution | string | ms | | jdkDistro | Select or enter a JDK distribution | string | ms |
| installGradle | Install Gradle, a build automation tool for multi-language software development | boolean | - | | installGradle | Install Gradle, a build automation tool for multi-language software development | boolean | false |
| installMaven | Install Maven, a management tool for Java | boolean | - | | gradleVersion | Select or enter a Gradle version | string | latest |
| installMaven | Install Maven, a management tool for Java | boolean | false |
| mavenVersion | Select or enter a Maven version | string | latest |
| installAnt | Install Ant, a software tool for automating software build processes | boolean | false |
| antVersion | Select or enter an Ant version | string | latest |
## Customizations
### VS Code Extensions
- `vscjava.vscode-java-pack`
## License ## License
For the Java Feature from this repository, see [NOTICE.txt](https://github.com/devcontainers/features/tree/main/src/java/NOTICE.txt) for licensing information on JDK distributions. For the Java Feature from this repository, see [NOTICE.txt](https://github.com/devcontainers/features/tree/main/src/java/NOTICE.txt) for licensing information on JDK distributions.
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.
--- ---
_Note: This file was auto-generated from the [devcontainer-feature.json](https://github.com/devcontainers/features/blob/main/src/java/devcontainer-feature.json). Add additional notes to a `NOTES.md`._ _Note: This file was auto-generated from the [devcontainer-feature.json](https://github.com/devcontainers/features/blob/main/src/java/devcontainer-feature.json). Add additional notes to a `NOTES.md`._

View file

@ -1,6 +1,6 @@
{ {
"id": "java", "id": "java",
"version": "1.0.9", "version": "1.2.2",
"name": "Java (via SDKMAN!)", "name": "Java (via SDKMAN!)",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/java", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/java",
"description": "Installs Java, SDKMAN! (if not installed), and needed dependencies.", "description": "Installs Java, SDKMAN! (if not installed), and needed dependencies.",
@ -33,13 +33,49 @@
"default": false, "default": false,
"description": "Install Gradle, a build automation tool for multi-language software development" "description": "Install Gradle, a build automation tool for multi-language software development"
}, },
"gradleVersion": {
"type": "string",
"proposals": [
"latest",
"7.5.1",
"6.9.3",
"5.6.4"
],
"default": "latest",
"description": "Select or enter a Gradle version"
},
"installMaven": { "installMaven": {
"type": "boolean", "type": "boolean",
"default": false, "default": false,
"description": "Install Maven, a management tool for Java" "description": "Install Maven, a management tool for Java"
},
"mavenVersion": {
"type": "string",
"proposals": [
"latest",
"3.8.6",
"3.6.3",
"3.5.4"
],
"default": "latest",
"description": "Select or enter a Maven version"
},
"installAnt": {
"type": "boolean",
"default": false,
"description": "Install Ant, a software tool for automating software build processes"
},
"antVersion": {
"type": "string",
"proposals": [
"latest",
"1.10.12",
"1.9.15"
],
"default": "latest",
"description": "Select or enter an Ant version"
} }
}, },
"buildArg": "_VSC_INSTALL_JAVA",
"customizations": { "customizations": {
"vscode": { "vscode": {
"extensions": [ "extensions": [
@ -53,6 +89,9 @@
"containerEnv": { "containerEnv": {
"SDKMAN_DIR": "/usr/local/sdkman", "SDKMAN_DIR": "/usr/local/sdkman",
"JAVA_HOME": "/usr/local/sdkman/candidates/java/current", "JAVA_HOME": "/usr/local/sdkman/candidates/java/current",
"PATH": "/usr/local/sdkman/bin:/usr/local/sdkman/candidates/java/current/bin:/usr/local/sdkman/candidates/gradle/current/bin:/usr/local/sdkman/candidates/maven/current/bin:${PATH}" "PATH": "/usr/local/sdkman/bin:/usr/local/sdkman/candidates/java/current/bin:/usr/local/sdkman/candidates/gradle/current/bin:/usr/local/sdkman/candidates/maven/current/bin:/usr/local/sdkman/candidates/ant/current/bin:${PATH}"
} },
"installsAfter": [
"ghcr.io/devcontainers/features/common-utils"
]
} }

45
src/java/install.sh Executable file → Normal file
View file

@ -9,21 +9,28 @@
# #
# Syntax: ./java-debian.sh [JDK version] [SDKMAN_DIR] [non-root user] [Add to rc files flag] # Syntax: ./java-debian.sh [JDK version] [SDKMAN_DIR] [non-root user] [Add to rc files flag]
JAVA_VERSION=${VERSION:-"lts"} JAVA_VERSION="${VERSION:-"lts"}"
INSTALL_GRADLE=${INSTALLGRADLE:-"false"} INSTALL_GRADLE="${INSTALLGRADLE:-"false"}"
INSTALL_MAVEN=${INSTALLMAVEN:-"false"} GRADLE_VERSION="${GRADLEVERSION:-"latest"}"
JDK_DISTRO=${JDKDISTRO} INSTALL_MAVEN="${INSTALLMAVEN:-"false"}"
MAVEN_VERSION="${MAVENVERSION:-"latest"}"
INSTALL_ANT="${INSTALLANT:-"false"}"
ANT_VERSION="${ANTVERSION:-"latest"}"
JDK_DISTRO="${JDKDISTRO}"
export SDKMAN_DIR=${SDKMAN_DIR:-"/usr/local/sdkman"} export SDKMAN_DIR="${SDKMAN_DIR:-"/usr/local/sdkman"}"
USERNAME=${USERNAME:-"automatic"} USERNAME="${USERNAME:-"${_REMOTE_USER:-"automatic"}"}"
UPDATE_RC=${UPDATE_RC:-"true"} UPDATE_RC="${UPDATE_RC:-"true"}"
# Comma-separated list of java versions to be installed # Comma-separated list of java versions to be installed
# alongside JAVA_VERSION, but not set as default. # alongside JAVA_VERSION, but not set as default.
ADDITIONAL_VERSIONS=${ADDITIONALVERSIONS:-""} ADDITIONAL_VERSIONS="${ADDITIONALVERSIONS:-""}"
set -e set -e
# Clean up
rm -rf /var/lib/apt/lists/*
if [ "$(id -u)" -ne 0 ]; then if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1 exit 1
@ -65,8 +72,10 @@ updaterc() {
apt_get_update() apt_get_update()
{ {
echo "Running apt-get update..." if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then
apt-get update -y echo "Running apt-get update..."
apt-get update -y
fi
} }
# Checks if packages are installed and installs them if not # Checks if packages are installed and installs them if not
@ -102,13 +111,13 @@ sdk_install() {
elif echo "${requested_version}" | grep -oE "${full_version_check}" > /dev/null 2>&1; then elif echo "${requested_version}" | grep -oE "${full_version_check}" > /dev/null 2>&1; then
echo "${requested_version}" echo "${requested_version}"
else else
local regex="${prefix}\\K[0-9]+\\.[0-9]+\\.[0-9]+${suffix}" local regex="${prefix}\\K[0-9]+\\.?[0-9]*\\.?[0-9]*${suffix}"
local version_list=$(su ${USERNAME} -c ". \${SDKMAN_DIR}/bin/sdkman-init.sh && sdk list ${install_type} 2>&1 | grep -oP \"${regex}\" | tr -d ' ' | sort -rV") local version_list=$(su ${USERNAME} -c ". \${SDKMAN_DIR}/bin/sdkman-init.sh && sdk list ${install_type} 2>&1 | grep -oP \"${regex}\" | tr -d ' ' | sort -rV")
if [ "${requested_version}" = "latest" ] || [ "${requested_version}" = "current" ]; then if [ "${requested_version}" = "latest" ] || [ "${requested_version}" = "current" ]; then
requested_version="$(echo "${version_list}" | head -n 1)" requested_version="$(echo "${version_list}" | head -n 1)"
else else
set +e set +e
requested_version="$(echo "${version_list}" | grep -E -m 1 "^${requested_version//./\\.}([\\.\\s]|$)")" requested_version="$(echo "${version_list}" | grep -E -m 1 "^${requested_version//./\\.}([\\.\\s]|-|$)")"
set -e set -e
fi fi
if [ -z "${requested_version}" ] || ! echo "${version_list}" | grep "^${requested_version//./\\.}$" > /dev/null 2>&1; then if [ -z "${requested_version}" ] || ! echo "${version_list}" | grep "^${requested_version//./\\.}$" > /dev/null 2>&1; then
@ -166,14 +175,22 @@ if [ ! -z "${ADDITIONAL_VERSIONS}" ]; then
su ${USERNAME} -c ". ${SDKMAN_DIR}/bin/sdkman-init.sh && sdk default java ${JAVA_VERSION}" su ${USERNAME} -c ". ${SDKMAN_DIR}/bin/sdkman-init.sh && sdk default java ${JAVA_VERSION}"
fi fi
# Install Ant
if [[ "${INSTALL_ANT}" = "true" ]] && ! ant -version > /dev/null; then
sdk_install ant ${ANT_VERSION}
fi
# Install Gradle # Install Gradle
if [[ "${INSTALL_GRADLE}" = "true" ]] && ! gradle --version > /dev/null; then if [[ "${INSTALL_GRADLE}" = "true" ]] && ! gradle --version > /dev/null; then
sdk_install gradle latest sdk_install gradle ${GRADLE_VERSION}
fi fi
# Install Maven # Install Maven
if [[ "${INSTALL_MAVEN}" = "true" ]] && ! mvn --version > /dev/null; then if [[ "${INSTALL_MAVEN}" = "true" ]] && ! mvn --version > /dev/null; then
sdk_install maven latest sdk_install maven ${MAVEN_VERSION}
fi fi
# Clean up
rm -rf /var/lib/apt/lists/*
echo "Done!" echo "Done!"

View file

@ -3,11 +3,11 @@
set -e set -e
JAVA_VERSION=${1:-"default"} JAVA_VERSION="${1:-"default"}"
SDKMAN_DIR=${2:-"/usr/local/sdkman"} SDKMAN_DIR="${2:-"/usr/local/sdkman"}"
USERNAME=${3:-"automatic"} USERNAME="${USERNAME:-"${_REMOTE_USER:-"automatic"}"}"
UPDATE_RC=${4:-"true"} UPDATE_RC="${4:-"true"}"
ADDITIONAL_JAVA_VERSION=11 ADDITIONAL_JAVA_VERSION="11"
cd "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
chmod +x install.sh chmod +x install.sh

View file

@ -10,3 +10,10 @@ minikube addons enable ingress
# Run this to forward to localhost in the background # Run this to forward to localhost in the background
nohup kubectl port-forward --pod-running-timeout=24h -n ingress-nginx service/ingress-nginx-controller :80 & nohup kubectl port-forward --pod-running-timeout=24h -n ingress-nginx service/ingress-nginx-controller :80 &
``` ```
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.

View file

@ -1,5 +1,5 @@
# Kubectl, Helm, and Minkube (kubectl-helm-minikube) # Kubectl, Helm, and Minikube (kubectl-helm-minikube)
Installs latest version of kubectl, Helm, and optionally minikube. Auto-detects latest versions and installs needed dependencies. Installs latest version of kubectl, Helm, and optionally minikube. Auto-detects latest versions and installs needed dependencies.
@ -7,9 +7,7 @@ Installs latest version of kubectl, Helm, and optionally minikube. Auto-detects
```json ```json
"features": { "features": {
"ghcr.io/devcontainers/features/kubectl-helm-minikube:1": { "ghcr.io/devcontainers/features/kubectl-helm-minikube:1": {}
"version": "latest"
}
} }
``` ```
@ -35,6 +33,13 @@ nohup kubectl port-forward --pod-running-timeout=24h -n ingress-nginx service/in
``` ```
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.
--- ---
_Note: This file was auto-generated from the [devcontainer-feature.json](https://github.com/devcontainers/features/blob/main/src/kubectl-helm-minikube/devcontainer-feature.json). Add additional notes to a `NOTES.md`._ _Note: This file was auto-generated from the [devcontainer-feature.json](https://github.com/devcontainers/features/blob/main/src/kubectl-helm-minikube/devcontainer-feature.json). Add additional notes to a `NOTES.md`._

View file

@ -1,7 +1,7 @@
{ {
"id": "kubectl-helm-minikube", "id": "kubectl-helm-minikube",
"version": "1.0.3", "version": "1.1.5",
"name": "Kubectl, Helm, and Minkube", "name": "Kubectl, Helm, and Minikube",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/kubectl-helm-minikube", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/kubectl-helm-minikube",
"description": "Installs latest version of kubectl, Helm, and optionally minikube. Auto-detects latest versions and installs needed dependencies.", "description": "Installs latest version of kubectl, Helm, and optionally minikube. Auto-detects latest versions and installs needed dependencies.",
"options": { "options": {
@ -12,7 +12,8 @@
"none", "none",
"1.23", "1.23",
"1.22", "1.22",
"1.21" "1.21",
"none"
], ],
"default": "latest", "default": "latest",
"description": "Select or enter a Kubernetes version to install" "description": "Select or enter a Kubernetes version to install"
@ -20,7 +21,8 @@
"helm": { "helm": {
"type": "string", "type": "string",
"proposals": [ "proposals": [
"latest" "latest",
"none"
], ],
"default": "latest", "default": "latest",
"description": "Select or enter a Helm version to install" "description": "Select or enter a Helm version to install"
@ -28,24 +30,21 @@
"minikube": { "minikube": {
"type": "string", "type": "string",
"proposals": [ "proposals": [
"latest" "latest",
"none"
], ],
"default": "latest", "default": "latest",
"description": "Select or enter a Minikube version to install" "description": "Select or enter a Minikube version to install"
} }
}, },
"customizations": {
"vscode": {
"extensions": [
"ms-kubernetes-tools.vscode-kubernetes-tools"
]
}
},
"mounts": [ "mounts": [
{ {
"source": "minikube-config", "source": "minikube-config",
"target": "/home/vscode/.minikube", "target": "/home/vscode/.minikube",
"type": "volume" "type": "volume"
} }
],
"installsAfter": [
"ghcr.io/devcontainers/features/common-utils"
] ]
} }

View file

@ -9,17 +9,21 @@
set -e set -e
# Clean up
rm -rf /var/lib/apt/lists/*
KUBECTL_VERSION="${VERSION:-"latest"}" KUBECTL_VERSION="${VERSION:-"latest"}"
HELM_VERSION="${HELM:-"latest"}" HELM_VERSION="${HELM:-"latest"}"
MINIKUBE_VERSION="${MINIKUBE:-"none"}" # latest is also valid MINIKUBE_VERSION="${MINIKUBE:-"latest"}" # latest is also valid
KUBECTL_SHA256="${KUBECTL_SHA256:-"automatic"}" KUBECTL_SHA256="${KUBECTL_SHA256:-"automatic"}"
HELM_SHA256="${HELM_SHA256:-"automatic"}" HELM_SHA256="${HELM_SHA256:-"automatic"}"
MINIKUBE_SHA256="${MINIKUBE_SHA256:-"automatic"}" MINIKUBE_SHA256="${MINIKUBE_SHA256:-"automatic"}"
USERNAME=${USERNAME:-"automatic"} USERNAME="${USERNAME:-"${_REMOTE_USER:-"automatic"}"}"
HELM_GPG_KEYS_URI="https://raw.githubusercontent.com/helm/helm/main/KEYS" HELM_GPG_KEYS_URI="https://raw.githubusercontent.com/helm/helm/main/KEYS"
GPG_KEY_SERVERS="keyserver hkp://keyserver.ubuntu.com:80 GPG_KEY_SERVERS="keyserver hkp://keyserver.ubuntu.com
keyserver hkp://keyserver.ubuntu.com:80
keyserver hkps://keys.openpgp.org keyserver hkps://keys.openpgp.org
keyserver hkp://keyserver.pgp.com" keyserver hkp://keyserver.pgp.com"
@ -50,22 +54,6 @@ if [ "$USERNAME" = "root" ]; then
USERHOME="/root" USERHOME="/root"
fi fi
# Get central common setting
get_common_setting() {
if [ "${common_settings_file_loaded}" != "true" ]; then
curl -sfL "https://aka.ms/vscode-dev-containers/script-library/settings.env" 2>/dev/null -o /tmp/vsdc-settings.env || echo "Could not download settings file. Skipping."
common_settings_file_loaded=true
fi
if [ -f "/tmp/vsdc-settings.env" ]; then
local multi_line=""
if [ "$2" = "true" ]; then multi_line="-z"; fi
local result="$(grep ${multi_line} -oP "$1=\"?\K[^\"]+" /tmp/vsdc-settings.env | tr -d '\0')"
if [ ! -z "${result}" ]; then declare -g $1="${result}"; fi
fi
echo "$1=${!1}"
}
# Figure out correct version of a three part version number is not passed # Figure out correct version of a three part version number is not passed
find_version_from_git_tags() { find_version_from_git_tags() {
local variable_name=$1 local variable_name=$1
@ -102,8 +90,10 @@ find_version_from_git_tags() {
apt_get_update() apt_get_update()
{ {
echo "Running apt-get update..." if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then
apt-get update -y echo "Running apt-get update..."
apt-get update -y
fi
} }
# Checks if packages are installed and installs them if not # Checks if packages are installed and installs them if not
@ -120,8 +110,7 @@ export DEBIAN_FRONTEND=noninteractive
# Install dependencies # Install dependencies
check_packages curl ca-certificates coreutils gnupg2 dirmngr bash-completion check_packages curl ca-certificates coreutils gnupg2 dirmngr bash-completion
if ! type git > /dev/null 2>&1; then if ! type git > /dev/null 2>&1; then
apt_get_update check_packages git
apt-get -y install --no-install-recommends git
fi fi
architecture="$(uname -m)" architecture="$(uname -m)"
@ -133,79 +122,83 @@ case $architecture in
*) echo "(!) Architecture $architecture unsupported"; exit 1 ;; *) echo "(!) Architecture $architecture unsupported"; exit 1 ;;
esac esac
# Install the kubectl, verify checksum if [ ${KUBECTL_VERSION} != "none" ]; then
echo "Downloading kubectl..." # Install the kubectl, verify checksum
if [ "${KUBECTL_VERSION}" = "latest" ] || [ "${KUBECTL_VERSION}" = "lts" ] || [ "${KUBECTL_VERSION}" = "current" ] || [ "${KUBECTL_VERSION}" = "stable" ]; then echo "Downloading kubectl..."
KUBECTL_VERSION="$(curl -sSL https://dl.k8s.io/release/stable.txt)" if [ "${KUBECTL_VERSION}" = "latest" ] || [ "${KUBECTL_VERSION}" = "lts" ] || [ "${KUBECTL_VERSION}" = "current" ] || [ "${KUBECTL_VERSION}" = "stable" ]; then
else KUBECTL_VERSION="$(curl -sSL https://dl.k8s.io/release/stable.txt)"
find_version_from_git_tags KUBECTL_VERSION https://github.com/kubernetes/kubernetes else
fi find_version_from_git_tags KUBECTL_VERSION https://github.com/kubernetes/kubernetes
if [ "${KUBECTL_VERSION::1}" != 'v' ]; then fi
KUBECTL_VERSION="v${KUBECTL_VERSION}" if [ "${KUBECTL_VERSION::1}" != 'v' ]; then
fi KUBECTL_VERSION="v${KUBECTL_VERSION}"
curl -sSL -o /usr/local/bin/kubectl "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/${architecture}/kubectl" fi
chmod 0755 /usr/local/bin/kubectl curl -sSL -o /usr/local/bin/kubectl "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/${architecture}/kubectl"
if [ "$KUBECTL_SHA256" = "automatic" ]; then chmod 0755 /usr/local/bin/kubectl
KUBECTL_SHA256="$(curl -sSL "https://dl.k8s.io/${KUBECTL_VERSION}/bin/linux/${architecture}/kubectl.sha256")" if [ "$KUBECTL_SHA256" = "automatic" ]; then
fi KUBECTL_SHA256="$(curl -sSL "https://dl.k8s.io/${KUBECTL_VERSION}/bin/linux/${architecture}/kubectl.sha256")"
([ "${KUBECTL_SHA256}" = "dev-mode" ] || (echo "${KUBECTL_SHA256} */usr/local/bin/kubectl" | sha256sum -c -)) fi
if ! type kubectl > /dev/null 2>&1; then ([ "${KUBECTL_SHA256}" = "dev-mode" ] || (echo "${KUBECTL_SHA256} */usr/local/bin/kubectl" | sha256sum -c -))
echo '(!) kubectl installation failed!' if ! type kubectl > /dev/null 2>&1; then
exit 1 echo '(!) kubectl installation failed!'
exit 1
fi
# kubectl bash completion
kubectl completion bash > /etc/bash_completion.d/kubectl
# kubectl zsh completion
if [ -e "${USERHOME}}/.oh-my-zsh" ]; then
mkdir -p "${USERHOME}/.oh-my-zsh/completions"
kubectl completion zsh > "${USERHOME}/.oh-my-zsh/completions/_kubectl"
chown -R "${USERNAME}" "${USERHOME}/.oh-my-zsh"
fi
fi fi
# kubectl bash completion if [ ${HELM_VERSION} != "none" ]; then
kubectl completion bash > /etc/bash_completion.d/kubectl # Install Helm, verify signature and checksum
echo "Downloading Helm..."
# kubectl zsh completion find_version_from_git_tags HELM_VERSION "https://github.com/helm/helm"
if [ -e "${USERHOME}}/.oh-my-zsh" ]; then if [ "${HELM_VERSION::1}" != 'v' ]; then
mkdir -p "${USERHOME}/.oh-my-zsh/completions" HELM_VERSION="v${HELM_VERSION}"
kubectl completion zsh > "${USERHOME}/.oh-my-zsh/completions/_kubectl" fi
chown -R "${USERNAME}" "${USERHOME}/.oh-my-zsh" mkdir -p /tmp/helm
fi helm_filename="helm-${HELM_VERSION}-linux-${architecture}.tar.gz"
tmp_helm_filename="/tmp/helm/${helm_filename}"
# Install Helm, verify signature and checksum curl -sSL "https://get.helm.sh/${helm_filename}" -o "${tmp_helm_filename}"
echo "Downloading Helm..." curl -sSL "https://github.com/helm/helm/releases/download/${HELM_VERSION}/${helm_filename}.asc" -o "${tmp_helm_filename}.asc"
find_version_from_git_tags HELM_VERSION "https://github.com/helm/helm" export GNUPGHOME="/tmp/helm/gnupg"
if [ "${HELM_VERSION::1}" != 'v' ]; then mkdir -p "${GNUPGHOME}"
HELM_VERSION="v${HELM_VERSION}" chmod 700 ${GNUPGHOME}
fi curl -sSL "${HELM_GPG_KEYS_URI}" -o /tmp/helm/KEYS
mkdir -p /tmp/helm echo -e "disable-ipv6\n${GPG_KEY_SERVERS}" > ${GNUPGHOME}/dirmngr.conf
helm_filename="helm-${HELM_VERSION}-linux-${architecture}.tar.gz" gpg -q --import "/tmp/helm/KEYS"
tmp_helm_filename="/tmp/helm/${helm_filename}" if ! gpg --verify "${tmp_helm_filename}.asc" > ${GNUPGHOME}/verify.log 2>&1; then
curl -sSL "https://get.helm.sh/${helm_filename}" -o "${tmp_helm_filename}"
curl -sSL "https://github.com/helm/helm/releases/download/${HELM_VERSION}/${helm_filename}.asc" -o "${tmp_helm_filename}.asc"
export GNUPGHOME="/tmp/helm/gnupg"
mkdir -p "${GNUPGHOME}"
chmod 700 ${GNUPGHOME}
get_common_setting HELM_GPG_KEYS_URI
get_common_setting GPG_KEY_SERVERS true
curl -sSL "${HELM_GPG_KEYS_URI}" -o /tmp/helm/KEYS
echo -e "disable-ipv6\n${GPG_KEY_SERVERS}" > ${GNUPGHOME}/dirmngr.conf
gpg -q --import "/tmp/helm/KEYS"
if ! gpg --verify "${tmp_helm_filename}.asc" > ${GNUPGHOME}/verify.log 2>&1; then
echo "Verification failed!"
cat /tmp/helm/gnupg/verify.log
exit 1
fi
if [ "${HELM_SHA256}" = "automatic" ]; then
curl -sSL "https://get.helm.sh/${helm_filename}.sha256" -o "${tmp_helm_filename}.sha256"
curl -sSL "https://github.com/helm/helm/releases/download/${HELM_VERSION}/${helm_filename}.sha256.asc" -o "${tmp_helm_filename}.sha256.asc"
if ! gpg --verify "${tmp_helm_filename}.sha256.asc" > /tmp/helm/gnupg/verify.log 2>&1; then
echo "Verification failed!" echo "Verification failed!"
cat /tmp/helm/gnupg/verify.log cat /tmp/helm/gnupg/verify.log
exit 1 exit 1
fi fi
HELM_SHA256="$(cat "${tmp_helm_filename}.sha256")"
fi if [ "${HELM_SHA256}" = "automatic" ]; then
([ "${HELM_SHA256}" = "dev-mode" ] || (echo "${HELM_SHA256} *${tmp_helm_filename}" | sha256sum -c -)) curl -sSL "https://get.helm.sh/${helm_filename}.sha256" -o "${tmp_helm_filename}.sha256"
tar xf "${tmp_helm_filename}" -C /tmp/helm curl -sSL "https://github.com/helm/helm/releases/download/${HELM_VERSION}/${helm_filename}.sha256.asc" -o "${tmp_helm_filename}.sha256.asc"
mv -f "/tmp/helm/linux-${architecture}/helm" /usr/local/bin/ if ! gpg --verify "${tmp_helm_filename}.sha256.asc" > /tmp/helm/gnupg/verify.log 2>&1; then
chmod 0755 /usr/local/bin/helm echo "Verification failed!"
rm -rf /tmp/helm cat /tmp/helm/gnupg/verify.log
if ! type helm > /dev/null 2>&1; then exit 1
echo '(!) Helm installation failed!' fi
exit 1 HELM_SHA256="$(cat "${tmp_helm_filename}.sha256")"
fi
([ "${HELM_SHA256}" = "dev-mode" ] || (echo "${HELM_SHA256} *${tmp_helm_filename}" | sha256sum -c -))
tar xf "${tmp_helm_filename}" -C /tmp/helm
mv -f "/tmp/helm/linux-${architecture}/helm" /usr/local/bin/
chmod 0755 /usr/local/bin/helm
rm -rf /tmp/helm
if ! type helm > /dev/null 2>&1; then
echo '(!) Helm installation failed!'
exit 1
fi
fi fi
# Install Minikube, verify checksum # Install Minikube, verify checksum
@ -240,4 +233,7 @@ if ! type docker > /dev/null 2>&1; then
echo -e '\n(*) Warning: The docker command was not found.\n\nYou can use one of the following scripts to install it:\n\nhttps://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/docker-in-docker.md\n\nor\n\nhttps://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/docker.md' echo -e '\n(*) Warning: The docker command was not found.\n\nYou can use one of the following scripts to install it:\n\nhttps://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/docker-in-docker.md\n\nor\n\nhttps://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/docker.md'
fi fi
echo -e "\nDone!" # Clean up
rm -rf /var/lib/apt/lists/*
echo -e "\nDone!"

35
src/nix/NOTES.md Normal file
View file

@ -0,0 +1,35 @@
## OS Support
This Feature should work on recent versions of Debian/Ubuntu, RedHat Enterprise Linux, Fedora, RockyLinux, and Alpine Linux.
## Location of Flakes
Currently `flakeUri` works best with a remote URI (e.g., `github:nixos/nixpkgs/nixpkgs-unstable#hello`) as local files need to be in the image.
> Proposed support for lifecycle hooks in Features ([#60](https://github.com/devcontainers/spec/issues/60)) would allow for expressions files or Flakes to exist in the source tree to be automatically installed on initial container startup, but today you will have to manually add the appropriate install command to `postCreateCommand` to your `devcontainer.json` instead.
## Multi-user vs. single-user installs
This Dev Container Feature supports two installation models for Nix: multi-user and single user. Multi-user is the default, but each has pros and cons.
| Installation Model | Pros | Cons |
| --- | --- | --- |
| *Multi-User* | Nix can be used with any user including root.<br /><br />Also still works if the UID or GID of any user is updated. | Only works with Nix 2.11 and up due to a Nix installer limitation.<br /><br />Container must run either: run as root (but `remoteUser` in devcontainer.json can be non-root), or includes `sudo` with the `remoteUser` being configured to use it. <br /><br />Note that automated start of the `nix-daemon` requires passwordless `sudo` if the container itself (e.g., `containerUser`) is not running as root. Manual startup using `sudo` can require a password, however (more next). |
| *Single-User* | Does not require the container to run as root or `sudo` to be included in the image. | Only works with the user specified in the `remoteUser` property or an auto-detected user. If this user's UID/GID is updated, that user will no longer be able to work with Nix. This is primarily a consideration when running on Linux where the UID/GID is sync'd to the local user. |
### Manually starting the Nix daemon
If you have `sudo` in your base image, but have a password set so automatic startup is not possible, you can manually start the Nix daemon by running the following command in a terminal:
```bash
sudo /usr/local/share/nix-entrypoint.sh
```
This same command can be used to restart the daemon if it has stopped for some reason. Logs are available at `/tmp/nix-daemon.log`.
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.

63
src/nix/README.md Normal file
View file

@ -0,0 +1,63 @@
# Nix Package Manager (nix)
Installs the Nix package manager and optionally a set of packages.
## Example Usage
```json
"features": {
"ghcr.io/devcontainers/features/nix:1": {}
}
```
## Options
| Options Id | Description | Type | Default Value |
|-----|-----|-----|-----|
| version | Version of Nix to install. | string | latest |
| multiUser | Perform a multi-user install (instead of single user) | boolean | true |
| packages | Optional comma separated list of Nix packages to install in profile. | string | - |
| flakeUri | Optional URI to a Nix Flake to install in profile. | string | - |
| extraNixConfig | Optional comma separated list of extra lines to add to /etc/nix/nix.conf. | string | - |
## OS Support
This Feature should work on recent versions of Debian/Ubuntu, RedHat Enterprise Linux, Fedora, RockyLinux, and Alpine Linux.
## Location of Flakes
Currently `flakeUri` works best with a remote URI (e.g., `github:nixos/nixpkgs/nixpkgs-unstable#hello`) as local files need to be in the image.
> Proposed support for lifecycle hooks in Features ([#60](https://github.com/devcontainers/spec/issues/60)) would allow for expressions files or Flakes to exist in the source tree to be automatically installed on initial container startup, but today you will have to manually add the appropriate install command to `postCreateCommand` to your `devcontainer.json` instead.
## Multi-user vs. single-user installs
This Dev Container Feature supports two installation models for Nix: multi-user and single user. Multi-user is the default, but each has pros and cons.
| Installation Model | Pros | Cons |
| --- | --- | --- |
| *Multi-User* | Nix can be used with any user including root.<br /><br />Also still works if the UID or GID of any user is updated. | Only works with Nix 2.11 and up due to a Nix installer limitation.<br /><br />Container must run either: run as root (but `remoteUser` in devcontainer.json can be non-root), or includes `sudo` with the `remoteUser` being configured to use it. <br /><br />Note that automated start of the `nix-daemon` requires passwordless `sudo` if the container itself (e.g., `containerUser`) is not running as root. Manual startup using `sudo` can require a password, however (more next). |
| *Single-User* | Does not require the container to run as root or `sudo` to be included in the image. | Only works with the user specified in the `remoteUser` property or an auto-detected user. If this user's UID/GID is updated, that user will no longer be able to work with Nix. This is primarily a consideration when running on Linux where the UID/GID is sync'd to the local user. |
### Manually starting the Nix daemon
If you have `sudo` in your base image, but have a password set so automatic startup is not possible, you can manually start the Nix daemon by running the following command in a terminal:
```bash
sudo /usr/local/share/nix-entrypoint.sh
```
This same command can be used to restart the daemon if it has stopped for some reason. Logs are available at `/tmp/nix-daemon.log`.
## OS Support
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
`bash` is required to execute the `install.sh` script.
---
_Note: This file was auto-generated from the [devcontainer-feature.json](https://github.com/devcontainers/features/blob/main/src/nix/devcontainer-feature.json). Add additional notes to a `NOTES.md`._

View file

@ -0,0 +1,42 @@
{
"id": "nix",
"version": "1.1.3",
"name": "Nix Package Manager",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/nix",
"description": "Installs the Nix package manager and optionally a set of packages.",
"options": {
"version": {
"type": "string",
"proposals": ["latest", "2.11"],
"default": "latest",
"description": "Version of Nix to install."
},
"multiUser": {
"type": "boolean",
"default": true,
"description": "Perform a multi-user install (instead of single user)"
},
"packages": {
"type": "string",
"default": "",
"description": "Optional comma separated list of Nix packages to install in profile."
},
"flakeUri": {
"type": "string",
"default": "",
"description": "Optional URI to a Nix Flake to install in profile."
},
"extraNixConfig": {
"type": "string",
"default": "",
"description": "Optional comma separated list of extra lines to add to /etc/nix/nix.conf."
}
},
"installsAfter": [
"ghcr.io/devcontainers/features/common-utils"
],
"containerEnv": {
"PATH": "/nix/var/nix/profiles/default/bin:/nix/var/nix/profiles/default/sbin:${PATH}"
},
"entrypoint": "/usr/local/share/nix-entrypoint.sh"
}

130
src/nix/install.sh Executable file
View file

@ -0,0 +1,130 @@
#!/bin/bash
# Move to the same directory as this script
set -e
FEATURE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd "${FEATURE_DIR}"
# Option defaults
VERSION="${VERSION:-"latest"}"
MULTIUSER="${MULTIUSER:-"true"}"
PACKAGES="${PACKAGES//,/ }"
FLAKEURI="${FLAKEURI:-""}"
EXTRANIXCONFIG="${EXTRANIXCONFIG:-""}"
USERNAME="${USERNAME:-"${_REMOTE_USER:-"automatic"}"}"
if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi
# Import common utils
. ./utils.sh
detect_user USERNAME
if [ -e "/nix" ]; then
echo "(!) Nix is already installed! Skipping installation."
else
if [ "${USERNAME}" = "root" ] && [ "${MULTIUSER}" != "true" ]; then
echo "(!) A single user install is not allowed for root. Add a non-root user to your image or set multiUser to true in your feature configuration."
exit 1
fi
# Verify dependencies
apt_get_update_if_exists
check_command curl "curl ca-certificates" "curl ca-certificates" "curl ca-certificates"
check_command gpg2 gnupg2 gnupg gnupg2
check_command dirmngr dirmngr dirmngr dirmngr
check_command xz xz-utils xz xz
check_command git git git git
check_command xargs findutils findutils findutils
# Determine version
find_version_from_git_tags VERSION https://github.com/NixOS/nix "tags/"
# Download and verify install per https://nixos.org/download.html#nix-verify-installation
tmpdir="$(mktemp -d)"
echo "(*) Downloading Nix installer..."
set +e
curl -sSLf -o "${tmpdir}/install-nix" https://releases.nixos.org/nix/nix-${VERSION}/install
exit_code=$?
set -e
if [ "$exit_code" != "0" ]; then
# Handle situation where git tags are ahead of what was is available to actually download
echo "(!) Nix version ${VERSION} failed to download. Attempting to fall back one version to retry..."
find_prev_version_from_git_tags VERSION https://github.com/NixOS/nix "tags/"
curl -sSLf -o "${tmpdir}/install-nix" https://releases.nixos.org/nix/nix-${VERSION}/install
fi
cd "${FEATURE_DIR}"
# Do a multi or single-user setup based on feature config
if [ "${MULTIUSER}" = "true" ]; then
echo "(*) Performing multi-user install..."
sh "${tmpdir}/install-nix" --daemon
else
home_dir="$(eval echo ~${USERNAME})"
if [ ! -e "${home_dir}" ]; then
echo "(!) Home directory ${home_dir} does not exist for ${USERNAME}. Nix install will fail."
exit 1
fi
echo "(*) Performing single-user install..."
echo -e "\n**NOTE: Nix will only work for user ${USERNAME} on Linux if the host machine user's UID is $(id -u ${USERNAME}). You will need to chown /nix otherwise.**\n"
# Install per https://nixos.org/manual/nix/stable/installation/installing-binary.html#single-user-installation
mkdir -p /nix
chown ${USERNAME} /nix ${tmpdir}
su ${USERNAME} -c "sh \"${tmpdir}/install-nix\" --no-daemon --no-modify-profile"
# nix installer does not update ~/.bashrc, and USER may or may not be defined, so update rc/profile files directly to handle that
snippet='
if [ "${PATH#*$HOME/.nix-profile/bin}" = "${PATH}" ]; then if [ -z "$USER" ]; then USER=$(whoami); fi; . $HOME/.nix-profile/etc/profile.d/nix.sh; fi
'
update_rc_file "$home_dir/.bashrc" "${snippet}"
update_rc_file "$home_dir/.zshenv" "${snippet}"
update_rc_file "$home_dir/.profile" "${snippet}"
fi
rm -rf "${tmpdir}" "/tmp/tmp-gnupg"
fi
# Set nix config
mkdir -p /etc/nix
create_or_update_file /etc/nix/nix.conf 'sandbox = false'
if [ ! -z "${FLAKEURI}" ] && [ "${FLAKEURI}" != "none" ]; then
create_or_update_file /etc/nix/nix.conf 'experimental-features = nix-command flakes'
fi
# Extra nix config
if [ ! -z "${EXTRANIXCONFIG}" ]; then
OLDIFS=$IFS
IFS=","
read -a extra_nix_config <<< "$EXTRANIXCONFIG"
for line in "${extra_nix_config[@]}"; do
create_or_update_file /etc/nix/nix.conf "$line"
done
IFS=$OLDIFS
fi
# Create entrypoint if needed
if [ ! -e "/usr/local/share/nix-entrypoint.sh" ]; then
if [ "${MULTIUSER}" = "true" ]; then
echo "(*) Setting up entrypoint..."
cp -f nix-entrypoint.sh /usr/local/share/
else
echo -e '#!/bin/bash\nexec "$@"' > /usr/local/share/nix-entrypoint.sh
fi
chmod +x /usr/local/share/nix-entrypoint.sh
fi
# Install packages, flakes, etc if specified
chmod +x,o+r ${FEATURE_DIR} ${FEATURE_DIR}/post-install-steps.sh
if [ "${MULTIUSER}" = "true" ]; then
/usr/local/share/nix-entrypoint.sh
su ${USERNAME} -c "
. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
${FEATURE_DIR}/post-install-steps.sh
"
else
su ${USERNAME} -c "
. \$HOME/.nix-profile/etc/profile.d/nix.sh
${FEATURE_DIR}/post-install-steps.sh
"
fi
echo "Done!"

21
src/nix/nix-entrypoint.sh Executable file
View file

@ -0,0 +1,21 @@
#!/bin/bash
# Attempt to start daemon
set +e
if ! pidof nix-daemon > /dev/null 2>&1; then
start_ok=false
if [ "$(id -u)" = "0" ]; then
( . /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh; /nix/var/nix/profiles/default/bin/nix-daemon > /tmp/nix-daemon.log 2>&1 ) &
if [ "$?" = "0" ]; then
start_ok=true
fi
elif type sudo > /dev/null 2>&1; then
sudo -n sh -c '. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh; /nix/var/nix/profiles/default/bin/nix-daemon > /tmp/nix-daemon.log 2>&1' &
if [ "$?" = "0" ]; then
start_ok=true
fi
fi
if [ "${start_ok}" = "false" ]; then
echo -e 'Failed to start nix-daemon as root. Set multiUser to false in your feature configuration if you would\nprefer to run the container as a non-root. You may also start the daemon manually if you have sudo\ninstalled and configured for your user by running "sudo -c nix-daemon &"'
fi
fi
exec "$@"

18
src/nix/post-install-steps.sh Executable file
View file

@ -0,0 +1,18 @@
#!/bin/bash
set -e
echo "(*) Executing post-installation steps..."
# Install list of packages in profile if specified.
if [ ! -z "${PACKAGES}" ] && [ "${PACKAGES}" != "none" ]; then
echo "Installing packages \"${PACKAGES}\" in profile..."
nix-env --install ${PACKAGES}
fi
# Install Nix flake in profile if specified
if [ ! -z "${FLAKEURI}" ] && [ "${FLAKEURI}" != "none" ]; then
echo "Installing flake ${FLAKEURI} in profile..."
nix profile install "${FLAKEURI}"
fi
nix-collect-garbage --delete-old
nix-store --optimise

272
src/nix/utils.sh Executable file
View file

@ -0,0 +1,272 @@
# Function to run apt-get if needed
apt_get_update_if_needed()
{
export DEBIAN_FRONTEND=noninteractive
if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then
echo "Running apt-get update..."
apt-get update
else
echo "Skipping apt-get update."
fi
}
# Function to run apt-get if command exists
apt_get_update_if_exists()
{
if type apt-get > /dev/null 2>&1; then
apt-get update
fi
}
# Checks if packages are installed and installs them if not
check_packages() {
if type dpkg > /dev/null 2>&1 && dpkg -s $1 > /dev/null 2>&1; then
return 0
elif type apk > /dev/null 2>&1 && apk -e info $2 > /dev/null 2>&1; then
return 0
elif type rpm > /dev/null 2>&1 && rpm -q $3 > /dev/null 2>&1; then
return 0
else
echo "Unable to find package manager to check for packages."
exit 1
fi
install_packages "$@"
return $?
}
# Checks if command exists, installs it if not
# check_command <command> "<apt packages to install>" "<apk packages to install>" "<dnf/yum packages to install>"
check_command() {
command_to_check=$1
shift
if type "${command_to_check}" > /dev/null 2>&1; then
return 0
fi
install_packages "$@"
return $?
}
# Installs packages using the appropriate package manager (apt, apk, dnf, or yum)
# install_packages "<apt packages to install>" "<apk packages to install>" "<dnf/yum packages to install>"
install_packages() {
if type apt-get > /dev/null 2>&1; then
apt_get_update_if_needed
apt-get -y install --no-install-recommends $1
elif type apk > /dev/null 2>&1; then
apk add $2
elif type dnf > /dev/null 2>&1; then
dnf install -y $3
elif type yum > /dev/null 2>&1; then
yum install -y $3
else
echo "Unable to find package manager to install ${command_to_check}"
exit 1
fi
}
# If in automatic mode, determine if a user already exists, if not use root
detect_user() {
local user_variable_name=${1:-username}
local possible_users=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)")
if [ "${!user_variable_name}" = "auto" ] || [ "${!user_variable_name}" = "automatic" ]; then
declare -g ${user_variable_name}=""
for current_user in ${possible_users[@]}; do
if id -u "${current_user}" > /dev/null 2>&1; then
declare -g ${user_variable_name}="${current_user}"
break
fi
done
fi
if [ "${!user_variable_name}" = "" ] || [ "${!user_variable_name}" = "none" ] || ! id -u "${!user_variable_name}" > /dev/null 2>&1; then
declare -g ${user_variable_name}=root
fi
}
# Figure out correct version of a three part version number is not passed
find_version_from_git_tags() {
local variable_name=$1
local requested_version=${!variable_name}
if [ "${requested_version}" = "none" ]; then return; fi
local repository=$2
# Normally a "v" is used before the version number, but support alternate cases
local prefix=${3:-"tags/v"}
# Some repositories use "_" instead of "." for version number part separation, support that
local separator=${4:-"."}
# Some tools release versions that omit the last digit (e.g. go)
local last_part_optional=${5:-"false"}
# Some repositories may have tags that include a suffix (e.g. actions/node-versions)
local version_suffix_regex=$6
local escaped_separator=${separator//./\\.}
local break_fix_digit_regex
if [ "${last_part_optional}" = "true" ]; then
break_fix_digit_regex="(${escaped_separator}[0-9]+)?"
else
break_fix_digit_regex="${escaped_separator}[0-9]+"
fi
local version_regex="[0-9]+${escaped_separator}[0-9]+${break_fix_digit_regex}${version_suffix_regex//./\\.}"
# If we're passed a matching version number, just return it, otherwise look for a version
if ! echo "${requested_version}" | grep -E "^${versionMatchRegex}$" > /dev/null 2>&1; then
local version_list="$(git ls-remote --tags ${repository} | grep -oP "${prefix}\\K${version_regex}$" | tr -d ' ' | tr "${separator}" "." | sort -rV)"
if [ "${requested_version}" = "latest" ] || [ "${requested_version}" = "current" ] || [ "${requested_version}" = "lts" ]; then
declare -g ${variable_name}="$(echo "${version_list}" | head -n 1)"
else
set +e
declare -g ${variable_name}="$(echo "${version_list}" | grep -E -m 1 "^${requested_version//./\\.}([\\.\\s]|${version_suffix_regex//./\\.}|$)")"
set -e
fi
if [ -z "${!variable_name}" ] || ! echo "${version_list}" | grep "^${!variable_name//./\\.}$" > /dev/null 2>&1; then
echo -e "Invalid ${variable_name} value: ${requested_version}\nValid values:\n${version_list}" >&2
exit 1
fi
fi
echo "Adjusted ${variable_name}=${!variable_name}"
}
# Soft version matching that resolves a version for a given package in the *current apt-cache*
# Return value is stored in first argument (the unprocessed version)
apt_cache_version_soft_match() {
# Version
local variable_name="$1"
local requested_version=${!variable_name}
# Package Name
local package_name="$2"
# Exit on no match?
local exit_on_no_match="${3:-true}"
# Ensure we've exported useful variables
. /etc/os-release
local architecture="$(dpkg --print-architecture)"
dot_escaped="${requested_version//./\\.}"
dot_plus_escaped="${dot_escaped//+/\\+}"
# Regex needs to handle debian package version number format: https://www.systutorials.com/docs/linux/man/5-deb-version/
version_regex="^(.+:)?${dot_plus_escaped}([\\.\\+ ~:-]|$)"
set +e # Don't exit if finding version fails - handle gracefully
fuzzy_version="$(apt-cache madison ${package_name} | awk -F"|" '{print $2}' | sed -e 's/^[ \t]*//' | grep -E -m 1 "${version_regex}")"
set -e
if [ -z "${fuzzy_version}" ]; then
echo "(!) No full or partial for package \"${package_name}\" match found in apt-cache for \"${requested_version}\" on OS ${ID} ${VERSION_CODENAME} (${architecture})."
if $exit_on_no_match; then
echo "Available versions:"
apt-cache madison ${package_name} | awk -F"|" '{print $2}' | grep -oP '^(.+:)?\K.+'
exit 1 # Fail entire script
else
echo "Continuing to fallback method (if available)"
return 1;
fi
fi
# Globally assign fuzzy_version to this value
# Use this value as the return value of this function
declare -g ${variable_name}="=${fuzzy_version}"
echo "${variable_name}=${!variable_name}"
}
# Checks if a marker file exists with the correct contents
# check_marker <marker path> [argument to be validated]...
check_marker() {
local marker_path="$1"
shift
local verifier_string="$(echo "$@")"
if [ -e "${marker_path}" ] && [ "${verifier_string}" = "$(cat ${marker_path})" ]; then
return 1
else
return 0
fi
}
# Updates marker for future checking
# update_marker <marker path> [argument to be validated]...
update_marker() {
local marker_path="$1"
shift
mkdir -p "$(dirname "${marker_path}")"
echo "$(echo "$@")" > "${marker_path}"
}
# run_if_exists <command> <command arguments>...
run_if_exists() {
if [ -e "$1" ]; then
"$@"
fi
}
# run_as_user_if_exists <username> <command> <command arguments>...
run_as_user_if_exists() {
local username=$1
shift
if [ -e "$1" ]; then
local command_string="$@"
su "${username}" -c "${command_string//"/\\"}"
fi
}
# symlink_if_ne <source> <target>
symlink_if_ne() {
if [ ! -e "$2" ]; then
ln -s "$1" "$2"
fi
}
# Update a rc/profile file if it exists and string is not already present
update_rc_file() {
# see if folder containing file exists
local rc_file_folder="$(dirname "$1")"
if [ ! -d "${rc_file_folder}" ]; then
echo "${rc_file_folder} does not exist. Skipping update of $1."
elif [ ! -e "$1" ] || [[ "$(cat "$1")" != *"$2"* ]]; then
echo "$2" >> "$1"
fi
}
# Update a file if with string if not already present
# create_or_update_file <file> <string>
create_or_update_file() {
if [ ! -e "$1" ] || [[ "$(cat "$1")" != *"$2"* ]]; then
echo "$2" >> "$1"
fi
}
# Use semver logic to decrement a version number then look for the closest match
find_prev_version_from_git_tags() {
local variable_name=$1
local current_version=${!variable_name}
local repository=$2
# Normally a "v" is used before the version number, but support alternate cases
local prefix=${3:-"tags/v"}
# Some repositories use "_" instead of "." for version number part separation, support that
local separator=${4:-"."}
# Some tools release versions that omit the last digit (e.g. go)
local last_part_optional=${5:-"false"}
# Some repositories may have tags that include a suffix (e.g. actions/node-versions)
local version_suffix_regex=$6
# Try one break fix version number less if we get a failure. Use "set +e" since "set -e" can cause failures in valid scenarios.
set +e
major="$(echo "${current_version}" | grep -oE '^[0-9]+' || echo '')"
minor="$(echo "${current_version}" | grep -oP '^[0-9]+\.\K[0-9]+' || echo '')"
breakfix="$(echo "${current_version}" | grep -oP '^[0-9]+\.[0-9]+\.\K[0-9]+' 2>/dev/null || echo '')"
if [ "${minor}" = "0" ] && [ "${breakfix}" = "0" ]; then
((major=major-1))
declare -g ${variable_name}="${major}"
# Look for latest version from previous major release
find_version_from_git_tags "${variable_name}" "${repository}" "${prefix}" "${separator}" "${last_part_optional}"
# Handle situations like Go's odd version pattern where "0" releases omit the last part
elif [ "${breakfix}" = "" ] || [ "${breakfix}" = "0" ]; then
((minor=minor-1))
declare -g ${variable_name}="${major}.${minor}"
# Look for latest version from previous minor release
find_version_from_git_tags "${variable_name}" "${repository}" "${prefix}" "${separator}" "${last_part_optional}"
else
((breakfix=breakfix-1))
if [ "${breakfix}" = "0" ] && [ "${last_part_optional}" = "true" ]; then
declare -g ${variable_name}="${major}.${minor}"
else
declare -g ${variable_name}="${major}.${minor}.${breakfix}"
fi
fi
set -e
}

Some files were not shown because too many files have changed in this diff Show more