I am very new to containers and trying out Docker for the first time
I want to create a Docker Image which has PowerShell 5.1 installed along with PowershellGet and ExchangeOnlineManagement modules.
I am really lost as how to use a base image and update it with the modules needed above.
I would suggest to first pull and run the image. https://hub.docker.com/_/microsoft-powershell?tab=description
Start container interactively and see if it fulfills your needs:
docker run -it mcr.microsoft.com/powershell
If you want to create a customized Docker Image you need to create a Dockerfile.
And you can use it as base image and built you image on top of https://hub.docker.com/_/microsoft-powershell?tab=description:
# Indicates image that will be used as the base image.
FROM mcr.microsoft.com/powershell
...
# add your docker instructions e.g:
RUN powershell New-Item c:\test
...
Afterwards in the same directory in which you have your Dockerfile: docker build -t <username>/<image_name>:<tag_name> .
Related
I wanted to use singularity container on remote server, so I tried this command to create image:
singularity build --fakeroot ....
but when I enter the assembled container (singularity shell name.container) or try to run some program file thought exec, singularity can see, but can not open one folder. When I try to open it by cd there is this problem: bash: cd: name_folder: No such file or directory
Same container works perfect on my computer (sudo singularity build ...). Can you suggest anything, please?
How to run a simple PowerShell script after Docker container starts?
FROM ...
ENTRYPOINT ["powershell", "C:\scripts\remotetools.ps1"]
or
FROM ...
CMD ["powershell", "C:\scripts\remotetools.ps1"]
didn't work
Take the ENTRYPOINT/CMD out of the dockerfile and then build the image again, and run it. find the container ID with
docker container ls
Now run your command but passed through the exec function so you can see if it works and get some better debugs:
docker exec <HEX_CONTAINER_ID> powershell C:\scripts\remotetools.ps1
you may also require the --privileged flag if the script doesn't run, then you may be looking at a permissions issue
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
I notice that some steps in the Docker build takes more time than manually executing the same command in the container. To provide some context, the process of installing Matlab Compiler Runtime (MCR) is as follows:
Download MCR installer from MathWorks website
Unpack installation files
Run /bin/win64/setup.exe -mode silent -agreeToLicense yes (non-interactive install)
I created the following Dockerfile to set up MCR on a Microsoft windowsservercore image including dotnet-framework.
# Line 1: Use dotnet-framework base image
FROM microsoft/dotnet-framework
# Line 2: Download MCR installer (self-extracting executable) and save as ZIP file
ADD https://www.mathworks.com/supportfiles/downloads/R2014b/deployment_files/R2014b/installers/win64/MCR_R2014b_win64_installer.exe C:\\MCR_R2014b_win64_installer.zip
# Line 3: Use PowerShell
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
# Line 4: Unpack ZIP contents to installation folder
RUN Expand-Archive C:\\MCR_R2014b_win64_installer.zip -DestinationPath C:\\MCR_INSTALLER
# Line 5: Run the setup command for a non-interactive installation of MCR
RUN Start-Process C:\MCR_INSTALLER\bin\win64\setup.exe -ArgumentList '-mode silent', '-agreeToLicense yes' -Wait
# Line 6: Remove ZIP and installation folder after setup is complete
RUN Remove-Item -Force -Recurse C:\\MCR_INSTALLER, C:\\MCR_R2014b_win64_installer.zip
I build a new image using the command:
docker build -t analytics/dotnet-mcr --no-cache --force-rm .
The installation of MCR is very slow, when compared to stopping at Line 4 and then manually running the MCR setup from a container based on the ensuing image (using the exact same PowerShell command)... any reason why needs an extra 3-4 minutes when performing the same step via the Dockerfile based build?
Note: Best practices suggest using a download utility versus using ADD, but I don't have any constraints related to image size since I am removing intermediate images as well as deleting the downloaded installer and unpacked installation folder. Plus, I like seeing the cleaner download progress bar of the ADD command.
I appreciate any improvements/optimizations that may be suggested.
Docker uses layers. According to it documentation each RUN command will create a layer. In your scenario, each layer will store the data related to the RUN command, so removing MCR_R2014b_win64_installer.zip as separate step will cause extra space in previous layers. I would recommend reducing RUN commands where it is possible.
Please check repo for more help.
EDIT: The problem is the COMPOSE_CONVERT_WINDOWS_PATHS environment variable isn't getting set. I tried adding it to the Dockerfile and to a .env file but its not being set. I can't set any new environment variables. Its like its building it from a cached Dockerfile.
I was running docker-composer up after deleting the container, but this didn't recreate a new container, even when adding --force-recreate, it created the container from the old Dockerfile. So I ran docker build ./ instead, and it built a new container, it reinstalled all the packages, and it said that it was setting the new environment variables, but in the finished container, when I check kinematic, I see the new environment variables aren't set. But all of the old environment variables that were set when I built the container for the first time, they're all set. I don't know why this is happening, why I can't create a new container from the updated Dockerfile.
I've found a number of threads about this error, it happens when trying to mount a volume in Windows docker-tools. When I run docker-compose up, I get this error:
ERROR: for web Cannot create container for service web: Invalid bind mount spec "C:\\path\\to\\project:/app:rw": Invalid volume specification: 'C:\path\to\project:/app:rw'
[31mERROR[0m: Encountered errors while bringing up the project.
In the docker-compose file I have this:
volumes:
- ./:/app
I tried setting this environment variable:
COMPOSE_CONVERT_WINDOWS_PATHS=1
to 1, as that worked for some people in another thread but its not working in this case. I tried adding an absolute path in linux like format:
volumes:
- /c/path/to/project:/app
and I get this error:
ERROR: for web Cannot create container for service web: create \c\path\to\project: "\\c\\path\\to\\project" includes invalid characters for a local volume name, only "[a-zA-Z0-9][a-zA-Z0-9_.-]" are allowed
Notice it reversed the forward slashes. Changing:
ENV COMPOSE_CONVERT_WINDOWS_PATHS=0
to 0 like that didn't change anything.
If I give a Windows format absolute directory, I get the first error again. Both of those errors, I get them if I point to a directory that doesn't exist.
Has anyone here figured out a way to resolve this?
So, if this problem exists, you should create new Windows environment variable called COMPOSE_CONVERT_WINDOWS_PATHS and set it to 1. Or you can create .env file in the path docker-compose.yml is placed with following content:
COMPOSE_CONVERT_WINDOWS_PATHS=1
..
cat >.env
COMPOSE_CONVERT_WINDOWS_PATHS=1
It looks like your COMPOSE_CONVERT_WINDOWS_PATHS=1 environment variable is not read by docker cli (powershell). you can try to run Get-childItem Env: command from your powershell console to get the list of environment variable which has been set in your powershell console. the output is like below:
Name Value
---- -----
COMPOSE_CONVERT_WINDOWS_PATHS 1
COMSPEC C:\WINDOWS\system32\cmd.exe
DOCKER_CERT_PATH C:\Users\devsa\.docker\machine\machines\default
DOCKER_HOST tcp://192.168.99.100:2376
DOCKER_TLS_VERIFY 1
...
If you don't see the COMPOSE_CONVERT_WINDOWS_PATHS=1 variable in your powershell console, it means the variable has not been set yet. To set the environment variable via powershell console, try this command:
$env:COMPOSE_CONVERT_WINDOWS_PATHS=1
it will set the environment variable in your power shell console check this powershell documentation for full documentation. Try to run the Get-childItem Env: command again to check whether the variable has been already set or not. if the variable has been set, you can try to run docker-compose up -d again.
After setting the environment variable to COMPOSE_CONVERT_WINDOWS_PATHS=1 try below setting in docker-compose
- ./app-demo:/dockermount under volumes
It worked for me