I touched Docker for the first time yesterday, and I don't know much about web server administration in general. Just a heads up.
I'm struggling to make a simple PHP "hello world" run inside a Docker container. I have built a Docker container with the following dockerfile:
FROM nanoserver/iis
MAINTAINER nanoserver.es#gmail.com
ADD http://windows.php.net/downloads/releases/php-5.6.31-Win32-VC11-x64.zip php.zip
ADD https://nanoserver.es/nanofiles/vcruntime140.dll C:\\Windows\\System32\\vcruntime140.dll
ADD https://nanoserver.es/nanofiles/iisfcgi.dll C:\\Windows\\System32\\inetsrv\\iisfcgi.dll
ADD https://nanoserver.es/nanofiles/info.dll C:\\inetpub\\wwwroot\\info.php
COPY hello.php C:\\inetpub\\wwwroot\\hello.php
ENV PHP C:\\php
RUN powershell -command Expand-Archive -Path c:\php.zip -DestinationPath C:\php
RUN setx PATH /M %PATH%;C:\php
ADD https://nanoserver.es/nanofiles/php.ini C:\\php\\php.ini
RUN powershell -command \
rm C:\Windows\System32\inetsrv\config\Applicationhost.config ; \
Invoke-WebRequest -uri https://nanoserver.es/nanofiles/Applicationhost.txt -outfile C:\\Windows\\System32\\inetsrv\\config\\Applicationhost.config ; \
Remove-Item c:\php.zip -Force
# The above request fails, but I don't see how it would be relevant to my question.
CMD ["powershell.exe"]
I would expect this Dockerfile to create a container with c:\inetpub\wwwroot\info.php, c:\inetpub\wwwroot\hello.php and c:\php. However, Powershell inside the container gives me this output:
PS C:\inetpub\wwwroot> ls
Directory: C:\inetpub\wwwroot
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 4/11/2017 11:55 AM 703 iisstart.htm
-a---- 4/11/2017 11:55 AM 99710 iisstart.png
It feels like there is some fundamental that I haven't grasped. Could someone help me out here?
On windows you have to use forward slashes in paths in the Dockerfile.
Official docs: https://learn.microsoft.com/en-us/virtualization/windowscontainers/manage-docker/manage-windows-dockerfile
From docs
On Windows, the destination format must use forward slashes. For example, these are valid COPY instructions.
COPY test1.txt /temp/
COPY test1.txt c:/temp/
However, the following will NOT work.
COPY test1.txt c:\temp\
If either source or destination include whitespace, enclose the path in square brackets and double quotes.
COPY ["<source>", "<destination>"]
Also note that copying to non-existing paths in the image normally do not trigger an error. The directory must exist.
Related
Is there a way to start a PHP script that starts when the docker containers are started with docker compose up -d?
E.g. if there are two containers: One of them is the PHP-Container and the other one is a MariaDB-Container. The PHP-Script should collect data from an API and save them into the MariaDB-Container when the docker containers are started.
I tried to use
CMD [php script.php]
in the Dockerfile and tried to modify the ENTRYPOINT of the Dockerfile:
COPY start-container /usr/local/bin/start-container
RUN chmod +x /usr/local/bin/start-container
ENTRYPOINT ["start-container"]
I also tried it with wait-for-it following this guide, put the "wait-for-it.sh" in the same folder as the Dockerfile and added following lines to the dockerfile:
COPY wait-for-it.sh wait-for-it.sh
RUN chmod +x wait-for-it.sh
CMD ["./wait-for-it.sh", "mariadb:3306" , "--strict" , "--timeout=60", "start_data_collection.sh"]
I also wrote a bash-script that starts the php script because I was not sure whether the php script can be executed from a dockerfile. But nothing seems to work and I don't know what to do next.
You can simply wait for mysql in your bash script :
while !(mysqladmin ping > /dev/null 2>&1)
do
sleep 3
done
and then call your php script.
You can use --host/--port option on mysqladmin to point to your other container. Be aware that you might need to handle the authentication to the mysql server.
If you don't want to do that, and keep the simple tcp check, you should add a -- like so, if we follow the examples from the github you linked :
CMD ["./wait-for-it.sh", "mariadb:3306" , "--strict" , "--timeout=60", "--", "start_data_collection.sh"]
Because you want to run start_data_collection.sh at the end of wait-for-it.sh, you don't want to pass it as argument to the wait-for-it.sh script
Is it possible to redirect a plain text log file to stderr within a Docker container that is writable by PHP?
I have a PHP application that is writing to a file and we're trying to move it into a Docker container without changing any code. I've tried symlinking but this results in permissions errors.
Not sure what type of symlinking you tried but you should be able to do this with something like
RUN ln -sf /dev/stderr /path/to/your/text.log
In your Dockerfile (where the text.log path is the one inside the container).
I ended up finding this solution which uses a fifopipe to pipe the data into stdout.
# Allow `nobody` user to write to /dev/stderr
mkfifo -m 600 /tmp/logpipe
chown nobody:nobody /tmp/logpipe
cat <> /tmp/logpipe 1>&2 &
https://github.com/moby/moby/issues/6880#issuecomment-344114520
I'm developing a web server in C #, but I have some problems with BATCH files that get Apache and MySQL running.
The BATCH that makes NGINX work I could do, but PHP does not start, gives an error of syntax and also need help with it.
NGINX-START.BAT (NGINX starts, but PHP does not start and syntax error)
Start Directory: C:\Users\NETO\Documents\Visual Studio 2010\Projects\MHServer\MHServer\bin\Debug\Server\Files\NGINX
Target Directory: C:\Users\NETO\Documents\Visual Studio 2010\Projects\MHServer\MHServer\bin\Debug\ with Php\php-cgi.exe
Error message: The syntax of the file name, directory name or volume label is incorrect.
The system can not find the path specified.
#ECHO OFF
cd \%CD%\
cd ..
cd ..
cd ..
cd Nginx
start nginx
set PATH=\Php;%PATH%
\Php\php-cgi.exe -b 127.0.0.1:9000
:exit
Apache-start.bat (Apache does not start and syntax error)
Error message: The syntax of the file name, directory name or volume label is incorrect.
The system can not find the path specified.
#ECHO OFF
cd \%CD%\
cd ..
cd ..
cd ..
\Apache\bin\Apache.exe
MySQL-start.bat (MySQL does not start and syntax error)
Error message: The syntax of the file name, directory name or volume label is incorrect.
The system can not find the path specified.
#ECHO OFF
cd \%CD%\
cd ..
cd ..
cd ..
\MySql\bin\mysqld.exe --defaults-file=\MySql\my.ini --standalone --console
:exit
Folder Structure (Folders of programs and files)
[C:\MHServer\Apache] - Apache Path
[C:\MHServer\MySql] - MySQL Path
[C:\MHServer\Nginx] - NGINX Path
[C:\MHServer\Php] - PHP Path
BAT folder files
[C:\MHServer\Server\Files\Apache] - Apache BAT Files
[C:\MHServer\Server\Files\MySQL] - MySQL BAT Files
[C:\MHServer\Server\Files\NGINX] - NGINX BAT Files
File Structure
/Files/
/Files/Apache/
/Files/MySQL/
/Files/NGINX/
I am not very good with BAT files, so I have come to you for help!
You just need to remove the backslashes from before the relative directory names.
For example:
\Apache\bin\Apache.exe
should be
Apache\bin\Apache.exe
Also, if you want to add your PHP directory to the PATH environmental variable in NGINX-START.BAT, you will need to use the full path, not a relative one. Something like this will work:
set PATH=%CD%\Php;%PATH%
Also, what are you trying to do with the cd \%CD%\? That should give an error on its own, so remove that from all of the scripts too.
So your first batch file should look like this:
#ECHO OFF
cd ..
cd ..
cd ..
cd Nginx
start nginx
cd ..
set PATH=%CD%\Php;%PATH%
Php\php-cgi.exe -b 127.0.0.1:9000
:exit
I'm trying in php to move a folder but keep both files in the dest folder if exist duplicate.
i tried todo that in recursion but its too complicated so many things can go wrong for example file premissions and duplicate files\folders.
im trying to work with system() command and i cant figure out how to move files but keep backup if duplicate without destroying the extension
$last_line = system('mv --backup=t websites/test/ websites/test2/', $retval);
gives the following if file exist in both dirs:
ajax.html~
ajax.html~1
ajax.html~2
what im looking for is:
ajax~.html
ajax~1.html
ajax~2.html
or any other like (1), (2) ... but without ruining the extension of the file.
any ideas? please.
p.s must use the system() command.
For this problem, I get sed to find and swap those extensions after the fact in this function below (passing my target directory as my argument):
swap_file_extension_and_backup_number ()
{
IFS=$'\n'
for y in $(ls $1)
do
mv $1/`echo $y | sed 's/ /\\ /g'` $1/`echo "$y" | sed 's/\(\.[^~]\{3\}\)\(\.~[0-9]\{1,2\}~\)$/\2\1/g'`
done
}
The function assumes that your file extensions will be the normal 3 characters long, and this will find backups up to two digits long i.e. .~99~
Explanation:
This part $1/`echo $y | sed 's/ /\\ /g'` $1/`echo "$y"
represents the first argument (the original file) of mv but protects you from space characters by adding an escape.
The last part $1/`echo "$y" | sed 's/\(\.[^~]\{3\}\)\(\.~[0-9]\{1,2\}~\)$/\2\1/g' is of course the target file where two parenthetic groups are swapped .i.e. /\2\1/
if you want to keep the original files and just create a copy then use cp not mv.
If you want to create a backup archive then do a tar gzip of the folder like this
tar -pczf name_of_your_archive.tar.gz /path/to/directory/to/backup
rsync --ignore-existing --remove-source-files /path/to/source /path/to/dest
Use rsync with the --backup and --backup-dir options. eg:
rsync -a --backup --backup-dir /usr/local/backup/2013/03/20/ /path/to/source /path/to/dest
Every time a file might be overwritten it is copied to the folder given, plus the path to that item. eg: /path/to/dest/path/to/source/file.txt
From the looks of things, there don't seem to be any built in method for you to back up files while keeping the extension at the correct place. Could be wrong, but I was not able to find one that doesn't do what your original question already pointed out.
Since you said that it's complicated to copy the files over using php, perhaps you can do it the same way you are doing it right now, getting the files in the format
ajax.html~
ajax.html~1
ajax.html~2
Then using PHP to parse through the files and rename them to the format you want. This way you won't have to deal with permissions, and duplicate files, which are complications you mentioned. You just have to look for files with this format, and rename them.
I am not responding strictly to your question, but the case I am presenting here is very common and therefore valid!
Here's my hack!
TO USE WITH FILES:
#!/bin/bash
# It will find all the files according to the arguments in
# "<YOUR_ARGUMENT_TO_FIND_FILES>" ("find" command) and move them to the
# "<DEST_FOLDER>" folder. Files with the same name will follow the pattern:
# "same_name.ext", "same_name (1).ext", "same_name (2).ext",
# "same_name (3).ext"...
cd <YOUR_TARGET_FOLDER>
mkdir ./<DEST_FOLDER>
find ./ -iname "<YOUR_ARGUMENT_TO_FIND_FILES>" -type f -print0 | xargs -0 -I "{}" sh -c 'cp --backup=numbered "{}" "./<DEST_FOLDER>/" && rm -f "{}"'
cd ./<DEST_FOLDER>
for f_name in *.~*~; do
f_bak_ext="${f_name##*.}"
f_bak_num="${f_bak_ext//[^0-9]/}"
f_orig_name="${f_name%.*}"
f_only_name="${f_orig_name%.*}"
f_only_ext="${f_orig_name##*.}"
mv "$f_name" "$f_only_name ($f_bak_num).$f_only_ext"
done
cd ..
TO USE WITH FOLDERS:
#!/bin/bash
# It will find all the folders according to the arguments in
# "<YOUR_ARGUMENT_TO_FIND_FOLDERS>" ("find" command) and move them to the
# "<DEST_FOLDER>" folder. Folders with the same name will have their contents
# merged, however files with the same name WILL NOT HAVE DUPLICATES (example:
# "same_name.ext", "same_name (1).ext", "same_name (2).ext",
# "same_name (3).ext"...).
cd <YOUR_TARGET_FOLDER>
find ./ -path "./<DEST_FOLDER>" -prune -o -iname "<YOUR_ARGUMENT_TO_FIND_FOLDERS>" -type d -print0 | xargs -0 -I "{}" sh -c 'rsync -a "{}" "./<DEST_FOLDER>/" && rm -rf "{}"'
This solution might work in this case
cp --backup=simple src dst
Or
cp --backup=numbered src dst
You can also specify a suffix
I am writing a Makefile by hand to create a PHP extension lib using SWIG. I have the following directory structure:
wrappers/ # SWIG generated C++ wrappers and header
objects/ # I want to place my object files here
bin/ # I want to place my executable (shared lib) here
This is what my Makefile looks like:
CC=g++
CFLAGS=-fPIC -c -Wall
INCLUDES=`php-config --includes` -Iwrappers
LDFLAGS=-shared
SOURCES=foo_wrap.cpp \
foobar_wrap.cpp \
foofoobar_wrap.cpp \
foobarbar_wrap.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=php_foobarlib.so
all: wrappers/$(SOURCES) bin/$(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o objects/$(input)
.cpp.o:
$(CC) $(CFLAGS) $< -o objects/$(input)
clean:
rm -rf *o $(EXECUTABLE)
When I run make at the command line, I get the following error:
make: * No rule to make target foobar_wrap.cpp', needed byall'.
Stop.
I want to build the shared library using CMake instead. Could someone please post an outline of the CMakeLists file I need to create to build the shared library, taking into accounts the directory structure of the project - i.e. where I want the built objects and binaries to go.
You can specify in the Makefile the following:
SOURCES=wrappers/foo_wrap.cpp wrappers/fo. .... and so on,
and then remove wrappers/ from all:
As observed by you, this will create the object files in the wrappers directory. In order to avoid that look at the gcc/g++ option to place all object files into separate directory answer for a solution to this problem.
wrappers/$(SOURCES) expands to nonsense, prefixing only the first filename with the path.