I'm building a Docker image based from microsoft/powershell:ubuntu16.04. It builds properly without any error, however when I go to use it it doesn't have the imported module that I stated in the Dockerfile (which is a psd1 file from a GitHub repo cloned in the image.
I tried with a simple import of Microsoft's powershell management as well (seen below), and it also doesn't get imported. I ran the image interactively and the commands one by one and everything imported fine, so I don't know why it doesn't work through the Dockerfile build itself.
FROM microsoft/powershell:ubuntu16.04
WORKDIR /workdir
RUN pwsh -command "Import-Module Microsoft.PowerShell.Management"
CMD [ "pwsh", "-Command", "Get-Module" ]
Example psd1 file
FROM microsoft/powershell:ubuntu16.04
RUN apt-get update && apt-get install git -y
RUN git clone https://github.com/DTW-DanWard/PowerShell-Beautifier.git
RUN cp -a PowerShell-Beautifier/src/. /opt/microsoft/powershell/6.0.0-rc/Modules
ENTRYPOINT [ "pwsh", "-c" ]
CMD [ "Get-Help", "Edit-DTWBeautifyScript" ]
Because it happens in a wrong "context". For this to work the way you want it to work you need to use both these commands in 1 powershell session:
pwsh -command "Import-Module Microsoft.PowerShell.Management; Get-Module"
else it creates a layer where it ran that command, but when powershell stops all the imports are gone (and when the layer is done, it shuts down the container, so it doesnt preserve session state, only os state).
My dockerfile (working example):
FROM microsoft/powershell:ubuntu16.04
RUN pwsh -c "Install-Module AzureRM.netcore -Force"
CMD [ "pwsh" ]
Related
1. How can I prevent Gitlab from adding -NoProfile when creating the docker container?
2. What's the difference between using powershell with -NoProfile and without it?
3. Is there any way if I run powershell -NoProfile to somehow load/run the default profile and to revert the effect of setting -NoProfile flag?
And now the story behind these questions:
MSBuild (Visual Studio build tool command) fails to build Xamarin app when used in docker container started by Gitlab with Powershell -NoProfile.
I created a docker image for CI purspose and everything is working properly if I run the container manually, but when it is run during Gitlab runner job, it fails (more exactly msbuild /t:SignAndroidPackage fails, because of some file does not gets generated). I inspected this (put a sleep of 1 hour in gitlab-ci.yml and attached to the container on the runner machine) and found out that Gitlab starts the container with PowerShell -NoProfile...I tried that manually(start the container with -NoProfile) and I reproduced the issue.
the error is:
Could not find a part of the path 'C:\builds\gitlab\HMI.Framework\KDI\sub\HostApplicationToolkit\sub\KBle\KBle\sub\XamarinBluetooth\Source\Plugin.BLE.Android\Resources\Resource.Designer.cs'
Here the Resource.Designer.cs is missing (and it should be auto-generated during the build process)
This is the dockerFile:
# escape=`
# Use the latest Windows Server Core image with .NET Framework 4.8.
FROM mcr.microsoft.com/dotnet/framework/sdk:3.5-windowsservercore-ltsc2019
ENV VS_STUDIO_INSTALL_LINK=https://download.visualstudio.microsoft.com/download/pr/befdb1f9-8676-4693-b031-65ee44835915/c541feeaa77b97681f7693fc5bed2ff82b331b168c678af1a95bdb1138a99802/vs_Community.exe
ENV VS_INSTALLER_PATH=C:\TEMP\vs2019.exe
ENV ANDROID_COMPILE_SDK=29
# Restore the default Windows shell for correct batch processing.
SHELL ["cmd", "/S", "/C"]
ADD $VS_STUDIO_INSTALL_LINK $VS_INSTALLER_PATH
RUN %VS_INSTALLER_PATH% --quiet --wait --norestart --nocache --includeRecommended --includeOptional`
--add Microsoft.VisualStudio.Workload.NetCrossPlat `
--add Microsoft.VisualStudio.Workload.XamarinBuildTools `
|| IF "%ERRORLEVEL%"=="3010" EXIT 0
RUN del %VS_INSTALLER_PATH%
# set some util paths
RUN setx JAVA_HOME "c:\Program Files\Android\jdk\microsoft_dist_openjdk_1.8.0.25\"
RUN setx path "%path%;c:\Program Files (x86)\Android\android-sdk\tools\bin;c:\Program Files (x86)\Android\android-sdk\platform-tools"
# update android SDK with API 29
RUN echo y| sdkmanager "platforms;android-%ANDROID_COMPILE_SDK%"
#ENTRYPOINT ["powershell.exe", "-NoLogo", "-ExecutionPolicy", "Bypass"]
This is the gitlab-ci.yml
image: visualstudio2019-xamarin-ci:1.0-windowsservercore-ltsc2019
stages:
- build
- test
variables:
GIT_SUBMODULE_STRATEGY: 'recursive'
build_kdi:
stage: build
only:
- CI_CD
tags:
- docker-windows
script:
- '& "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe" ./src/KDI/KDI.sln /t:Restore /p:AndroidBuildApplicationPackage=true /p:Configuration=Release'
- '& "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe" /p:Configuration=Release /t:SignAndroidPackage /property:SolutionDir="C:\builds\gitlab\HMI.Framework\KDI\src\KDI\" /p:AndroidSigningKeyStore="C:\builds\gitlab\HMI.Framework\KDI\distribution\Android\KrohneAndroidKeystore.keystore" .\src\KDI\KDI\KDI.Android\KDI.Android.csproj'
run_bb_tests:
stage: test
only:
- CI_CD
tags:
- docker-windows
script:
- docker-ci/install_and_run_bb_tests.bat "phone_ip" "5555" arg1 arg2 || true
- adb pull /storage/emulated/0/Android/data/myApp/files/Exports/BBT_Exports/BBTests_CI C:\test_results
artifacts:
paths:
- c:\test_results\BBTests_CI #expire in 1 month by default
If I start this image using : docker run -it myImage powershell everything works well, but if I run it docker run -it myImage powershell -NoProfile, msbuild fails at some step in building the xamarin app
How can I prevent Gitlab from adding -NoProfile when creating the docker container?
Apparently you can't...yet but there is a feature request in place
What's the difference between using powershell with -NoProfile and without it?
A PowerShell profile is just a file that contains things, like custom functions, for a specific user. For instance, if I were to have Function Banana(){Write-Host "Awesome"} in my PowerShell profile e.g $Home[My ]Documents\PowerShell\Profile.ps1. Whenever I open up PowerShell, it loads that function automatically. So I can open PowerShell, type banana and have the string Awesome written to stdout. If I were to start powershell with -NoProfile, and enter banana, I'd get CommandNotFoundException.
source
Is there any way if I run powershell -NoProfile to somehow load/run the default profile and to revert the effect of setting -NoProfile flag?
Maybe. And I only say maybe because I haven't personally tested it, but in theory it should work. If the profile is in the container, all you have to do is dot source it.
. "C:\path\to\powershell\profile.ps1"
dot sourcing the .ps1 file will run anything within it, inside the current scope, which includes loading functions, if any are present.
dot source docs
My expertise on Gitlab is limited, but due to my overall experience with Windows containers, PowerShell, as well as the nature of PowerShell profiles, I have doubts that the profiling is the root cause of this issue, but I don't have enough information/evidence to definitively say. Hope this helps in some way!
I recently downloaded the new Windows Terminal. I have created the shortcut for opening the multiple panes(which is working fine). However, I am trying to execute a command for the respective pane.
wt -d <path> -c "cls && php artisan serve" ;
split-pane -p "Command Prompt" -H -d <path> -c "npm run watch"
I googled for the solution but no luck.
Is this even possible..?
I got a similar setup working.
Im running Windows Terminal version 1.8.1444.0
My goal was to setup a dotnet core app running in left pane and a react-app running in right pane:
wt -d "C:\path\to\dotnetcoreapp" -p "Command Promt" cmd /k dotnet watch run ; split-pane -d "C:\path\to\reactapp" cmd /k yarn start
Also tried to start an interactive elixir session: wt -d "C:\dev\elixir" cmd /k IEx which also worked fine...
The short answer is: Yes it is possible but it is a workaround.
The Challenges
wt.exe does not currently have a command line option to execute a
command from a split-pane
wsl.exe (which runs your default shell such as bash) does not currently support opening a shell with a command without exiting the shell right after the command is run.
The workaround
To get around the first challenge we can launch a custom profile that executes the command via wsl.exe in the key value pair (in settings json) "commandline": "wsl.exe 'commands go here"
To get around the second challenge we need to execute the wsl.exe 'commands go here' via powershell.exe because Powershell has a -NoExit option which will keep the shell open after the command is executed. So for example if you wanted to open a shell that runs wsl.exe (your linux shell) with the command watch ps then the line in the custom profile would look like this:
"commandline": "powershell.exe -NoExit -Command wsl.exe watch ps"
The Solution:
Create a profile in Windows Terminal settings.json for each command you want to run. Each profile should have a unique guid that you can generate in Powershell by running the command [guid]::NewGuid(). So the profile to run the command watch ps would look something like this:
{
"guid": "{b7041a85-5613-43c0-be35-92d19002404f}",
"name": "watch_ps",
"commandline": "powershell.exe -NoExit -Command wsl.exe watch ps",
"hidden": false,
"colorScheme": "One Half Dark"
},
Now you can open a tab in windows terminal with two panes, the pane on the right will run the command watch ps and the shell will stay open. Put something like the below line of code in your shortcut (or from the command line) where the value of the option -p is equal to the value of the profile you created. Each additional pane you open will need a profile that has the command you want to run in it.
wt split-pane -p "watch_ps"
I need to run a [Windows] Docker container as an executable, running a rather involved PowerShell script (invoking Java and .NET applications) and exiting. Docker documentation suggests using ENTRYPOINT for this purpose. So I went ahead and created a Dockerfile with the following contents:
FROM microsoft/dotnet-framework
COPY run.ps1 /
ENTRYPOINT [ "powershell.exe", "C:\\run.ps1" ]
The contents of run.ps1 (uber-simplified for this question):
gci
write-host "looks like everything is good!"
Then, I ran the following commands:
# Build the Docker image
docker build --rm -t testdockerps .
# Create/run container using above image
docker run -it testdockerps
The container ran successfully, displaying the contents of C:\ followed by the message - looks like everything is good!.
I have a couple of questions based on what my observations:
What is the default shell for a Windows based Docker container? Is there any way to set it to PowerShell, so I don't have to specify "powershell" as the first element of the ENTRYPOINT JSON array? Should I be using the SHELL command in the Dockerfile?
Creating and running the container takes about 3-4 seconds which is somewhat understandable, but after the PS1 script completes, it takes nearly a questionable 10 seconds for the container to exit and return to the command prompt. What may be the cause of this delay?
Yes you can specify powershell as default shell like below on top of DOCKERFILE
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'Continue'; $verbosePreference='Continue';"]
I'm not sure you can do anything about the time it takes to spin down your VM
For the life of me, I cannot seem to get my provisioning script to execute when I run my container. Down the road, I will need to pass in arguments to the docker run command to replace 'hiiii' and '123' for multiple container deployments.
This is my docker file
FROM microsoft/aspnet:3.5-windowsservercore-10.0.14393.1198
SHELL [“powershell”, “-Command”, “$ErrorActionPreference = ‘Stop’; $ProgressPreference = ‘SilentlyContinue’;”]
COPY *.ps1 /Container/
COPY [“wwwroot”, “/inetpub/wwwroot”]
COPY [“Admin”, “/Program Files (x86)Admin”]
COPY [“Admin/web.config”, “/Program Files (x86)/Admin/web_default.config”]
#ENTRYPOINT [“powershell”]
CMD [“powershell.exe”, -NoProfile, -File, C:\Container\Start-Admin.Docker.Cmd.ps1 -Parm1 ‘Hiiii’ -parm2 ‘123’]
I have also tried the shell version of CMD as follows
CMD powershell -NoProfile -File C:\Container\Start-Admin.Docker.Cmd.ps1 -Parm1 ‘Hiiii’ -Parm2 ‘123’
This is the command I am using.
docker image build -t image:v1:v1 .
docker run --name container -p 8001:80 -d image:v1
After I create and run the container I see that the script did not run, or failed. However, I can exec into powershell on the container and run the script manually and it works fine and I see all the changes that I need.
docker exec --interactive --tty container powershell
C:\Container\Start-Admin.Docker.Cmd.ps1 -Parm1 ‘Hiiii’ -Parm2 ‘123’
I am just at a loss as to what I am missing regarding CMD.
Thanks!
I was able to get it working the way I had hoped. Though I am still working out some details in the provisioning script, this is how I ended up getting the result I wanted from the docker side of things.
FROM microsoft/aspnet:3.5-windowsservercore-10.0.14393.1198
#The shell line needs to be removed and any RUN commands need to be immediately proceeded by 'powershell' eg RUN powershell ping google.com
#SHELL [“powershell”, “-Command”, “$ErrorActionPreference = ‘Stop’; $ProgressPreference = ‘SilentlyContinue’;”]
COPY *.ps1 /Container/
COPY [“wwwroot”, “/inetpub/wwwroot”]
COPY [“Admin”, “/Program Files (x86)Admin”]
COPY [“Admin/web.config”, “/Program Files (x86)/Admin/web_default.config”]
ENV myParm1 Hiiii
ENV myParm2 123
ENTRYPOINT ["powershell", "-NoProfile", "-Command", "C:\\Container\\Start-Admin.Docker.Cmd.ps1"]
CMD ["-parm1 $Env:myParm1 -parm2 $Env:myParm2"]
The docker run command looks like this
docker run -d -p 8001:80 -e "myParm1=byeeeee" --name=container image:v1
I hope this helps someone else that is in my boat. Thanks for all the answers!
You can give this a try. ARG passes the variable to shell accessible via PS $env: variable.
ARG parmOne=Hiiii
ARG parmTwo=123
# Run a native PowerShell session and pass the script as a command.
RUN ["powershell", "-NoProfile", "-Command", "C:\\Container\\Start-Admin.Docker.Cmd.ps1 -Parm1 $env:parmOne -parm2 $env:parmTwo"]
I am trying to use packer to provision awscli on a Windows machine. To install the awscli is use the following PowerShell script:
$download_url = 'https://s3.amazonaws.com/aws-cli/AWSCLI64.msi'
$downloaddestination = 'C:\Program Files\awscli.msi'
$checkpath='C:\Program Files\Amazon\AWSCLI'
if (Test-Path $downloaddestination) {
# // File exists do nothing
} else {
# // File does not exist download it
(New-Object System.Net.WebClient).DownloadFile($download_url, $downloaddestination)
}
$env:SEE_MASK_NOZONECHECKS = 1
Start-Process $downloaddestination /qn -Wait | Out-Null
Start-Sleep -Seconds 60
if (Test-Path $checkpath) {
Write-Host "awscli installed"
} else {
Write-Host "Installation failed"
}
I am unable to install awscli, its getting failed to install the MSI package even though its able to download the packege.
I use Python to install the cli, it makes updating easier too. I normally use cloud formation, cloud formation uses the userdata to invoke a script that is run by powershell.
The script looks like this:
mkdir c:\setup-downloads
cd \setup-downloads
curl https://www.python.org/ftp/python/3.7.3/python-3.7.3-amd64.exe --output python-inst.exe
.\python-inst.exe /quiet InstallAllUsers=1 PrependPath=1 Include_test=0
Start-Sleep -s 30
$env:Path += ";C:\Program Files\Python37"
$env:Path += ";C:\Program Files\Python37\Scripts"
pip3 install awscli
Create a directory somewhere mkdir c:\setup-downloads . Change to that directory cd \setup-downloads I then use curl to download python: curl https://www.python.org/ftp/python/3.7.3/python-3.7.3-amd64.exe --output python-inst.exe
Then I run the install using quiet mode, and I set it up to install itself into the path, and installed for everyone .\python-inst.exe /quiet InstallAllUsers=1 PrependPath=1 Include_test=0
I wait for this to finish Start-Sleep -s 30 But you need to restart the powershell to actually access python so I run the following to set the environment variables:
$env:Path += ";C:\Program Files\Python37"
$env:Path += ";C:\Program Files\Python37\Scripts"
Now that I have python installed, and the environment variables configured I can install the cli as follows:
pip3 install awscli
If you run aws --version it works
I tried #Jasons answer, calling the PowerShell file from an autoattend syncronusCommand block, however, I could not get pip3 command to be recognised.. setting the python env path inline I felt was a little hacky.
Check out - https://www.python.org/download/releases/2.5/msi/ - which explains that when using an MSI file the - installation can be initiated programmatically.
My PowerShell file now looks like this
Invoke-WebRequest -Uri https://awscli.amazonaws.com/AWSCLIV2.msi -Outfile "C:\aws.msi"
Start-Process -Wait -FilePath msiexec -ArgumentList /i, "c:\aws.msi", /qn
Now I have automated the install of aws cli on windows server.
I would suggest changing the approach and installing aws cli via pip the Python package manager that comes with the default Python installation.
Follow this guide to install Python silently on windows. Then you can just run the command below and it will install the awscli.
pip install awscli
You can use pip on windows, it's easy:
1. download and Install Python 2.7 for Win x64 in Python27 folder (default) [I had trouble with Python3.0 but I may have installed it wrong]
https://www.python.org/downloads/
2. in control panel, system, advanced settings add (ie., "new") to the user or system variable:
PYTHONPATH %PYTHONPATH%;C:\Python27\Lib
3. in control panel, system, advanced settings, edit the system PATH variable and add at the end:
;C:\Python27;C:\Python27\Scripts;C:\Program Files\Amazon\AWSCLI\
4. download the awscli package from
https://s3.amazonaws.com/aws-cli/AWSCLI64.msi
5. now you can run in the Windows DOS Command box: "pip install --upgrade awscli"
6. you can run cli commands in Windows DOS Command box, powershell or powershell ise. First run "aws configure" in powershell or win/dos command box
7. then you can run any CLI or CLI SDK command in powershell ise