How do I change timezone in a docker container? - docker

I am running docker container for my development stack which I pulled from docker-hub, the image is created for a different timezone than where my application is supposed to be deployed.
How do I change timezone in a docker container?
I tried to change the timezone config within the container by running
echo "Africa/Lusaka" > /etc/timezone
and restarted the container but I still get the same timezone.

You can override as suggest by #LinPy during the run stage, but if you want to set at your Dockerfile you can set using ENV as tzdata is already there in your base image.
FROM postgres:10
ENV TZ="Africa/Lusaka"
RUN date
Build
docker build -t dbtest .
RUN
docker run -it dbtest -c "date"
Now you can verify on DB side by running
show timezone;
You will see Central Africa Time in both container and Postgres
in the alpine base image, the environment variable will not work. You will need to run
RUN ls /usr/share/zoneinfo && \
cp /usr/share/zoneinfo/Europe/Brussels /etc/localtime && \
echo "Africa/Lusaka" > /etc/timezone && \

There's a few ways to do it .
You can declare the time zone directly as an environment variable in the docker compose file
environment:
- TZ=Asia/Singapore
- DEBIAN_FRONTEND=noninteractive
You can map the container's time zone and local time files to use that of the host machine in the docker compose file
volumes:
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
I personally prefer to use the second method, in this way , all of my containers will have the same time configuration as my host machine

Simply change the /etc/localtime to the time zone in the /usr/share/zoneinfo directory.
follow these steps:
first log into bash of your container:
docker exec -u 0 -it mycontainer bash
then remove the symbolic link file (/etc/localtime):
sudo rm -rf /etc/localtime
Identify the timezone you want to configure and create the symbolic link for it:
For instance, I would like to set Asia/Tehran timezone:
ln -s /usr/share/zoneinfo/Asia/Tehran /etc/localtime
Now verify it by:
date
and the output would be your timezone:
Sat Jan 30 14:22:17 +0330 2021

the best way is to use ENV in your run stage
-e TZ=Africa/Lusaka
and make sure that the package tzdata is present in the Container

A simpler method would be to add an env var to your deployment:
env:
- name: TZ
value: "Europe/London"
(kubernetes deployment yaml)

If you have TZ env set correctly and you still get the wrong time, make sure the tzdata system dependency is installed.

This question was about a postgres base, mine was about an Alpine base, but based on the Alpine Wiki, what I can glean of best practice means my Dockerfile looks like:
FROM alpine:3.14
RUN apk add --no-cache alpine-conf && \
setup-timezone -z Europe/London
https://wiki.alpinelinux.org/wiki/Alpine_setup_scripts#setup-timezone

For anyone who are using --env-file. add
# .env
TZ=Asia/Shanghai
To .env file, and it will get the time zone you want.

use
ls /usr/share/zoneinfo/
to show all zone

Related

Cronjob with docker-compose

I want to schedule a job in a docker container.
First of all after looking around i could stablish the container time zone correctly. When i use the command 'date' inside the terminal, it shows the hour of my city and country, but the cronjob works with the time zone that was especified by default in the container. I readed that it's necesary to tell cron, that the time zone has changed. I tried and environment variable TZ_CRON but it didnt work.I also restarted the cron service inside the container but it continued working in the same way.
I base my code in this repo
https://github.com/senorihl/docker-compose-cronjob
Then i sync the timezone with the command:
environment:
- TZ=America/Bogota
command: >
sh -c "ln -snf /usr/share/zoneinfo/$TZ /etc/localtime &&
echo $TZ > /etc/timezone"
entrypoint: sh /app/crontab.sh
Can you please help me with this?
The way this issue was solved:
I added this volume:
volumes:
-/etc/localtime:/etc/localtime:ro
Version of compose: 3
Related post:
Using docker-compose to set containers timezones

How to set environment variables within Dockerfile's RUN?

I need to set the output of a RUN command to be an environment variable that is available inside my container after it's built:
...
RUN ...
GO111MODULE=on go get github.com/emersion/hydroxide/cmd/hydroxide && \
echo "the_password" | hydroxide auth the_username#protonmail.com > bridge_password.txt && \
BRIDGE_PASSWORD=`sed -n 's/Password: Bridge password: //p' bridge_password.txt` && \
hydroxide smtp
...
Above, I need $BRIDGE_PASSWORD to be available in my NodeJS project (process.env.BRIDGE_PASSWORD). How can I achieve this?
You need to:
Declare your env var with the ENV command in your Dockerfile.
Substitute your current RUN with a command in your image entrypoint so that the variable gets set correctly everytime your start a new container and is available to any launched command.

How to update docker daylight saving schedule

We have a docker image using America/Sao_Paulo timezone.
Since the government changed the period of daylight saving time in Brazil, it looks like the docker image didn't get the update, even if the linux machine where the docker is installed was.
I think I've found something who solve this:
apt-get install -y tzdata
ln -fs /usr/share/zoneinfo/America/New_York /etc/localtime
dpkg-reconfigure --frontend noninteractive tzdata
I'm running this first at my Dockerfile.yml. Looks like it's solved.
You can set the environment variable TZ in the docker container to change the timezone.
For example:
docker run -e "TZ=America/Sao_Paulo" image_name

How to export an environment variable to a docker image?

I can define "static" environment variables in a Dockerfile with ENV, but is it possible to pass some value at build time to this variable? I'm attempting something like this, which doesn't work:
FROM phusion/baseimage
RUN mkdir -p /foo/2016/bin && \
FOOPATH=`ls -d /foo/20*/bin` && \
export FOOPATH
ENV PATH $PATH:$FOOPATH
Of course, in the real use case I'd be running/unpacking something that creates a directory whose name will change with different versions, dates, etc., and I'd like to avoid modifying the Dockerfile every time the directory name changes.
Edit: Since it appears it's not possible, the best workaround so far is using a symlink:
FROM phusion/baseimage
RUN mkdir -p /foo/2016/bin && \
FOOPATH=`ls -d /foo/20*/bin` && \
ln -s $FOOPATH /mypath
ENV PATH $PATH:/mypath
To pass a value in at build time, use an ARG.
FROM phusion/baseimage
RUN mkdir -p /foo/2016/bin && \
FOOPATH=`ls -d /foo/20*/bin` && \
export FOOPATH
ARG FOOPATH
ENV PATH $PATH:${FOOPATH}
Then you can run docker build --build-arg FOOPATH=/dir -t myimage .
Edit: from you comment, my answer above won't solve your issue. There's nothing in the Dockerfile you can update from the output of the run command, the output isn't parsed, only the resulting filesystem is saved. For this, I think you're best off in your run command writing the path to the image and read in from your /etc/profile or a custom entrypoint script. That depends on how you want to launch your container and the base image.

How to set PS1 in Docker Container

I want to set $PS1 environment variable to the container. It helps me to identify multilevel or complex docker environment setup. Currently docker container prompts with:
root#container-id#
If I can change it as following , I can identify the container by looking at the $PS1 prompt itself.
[Level-1]root#container-id#
I did experiments by exporting $PS1 by making my own image (Dockerfile), .profile file etc. But it's not reflecting.
I had the same problem but in docker-compose context.
Here is how I managed to make it work:
# docker-compose.yml
version: '3'
services:
my_service:
image: my/image
environment:
- "PS1=$$(whoami):$$(pwd) $$ "
Just pass PS1 value as an environment variable in docker-compose.yml configuration file.
Notice how dollars signs need to be escaped to prevent docker-compose from interpolating values (documentation).
This Dockerfile sets PS1 by doing:
RUN echo 'export PS1="[\u#docker] \W # "' >> /root/.bash_profile
We use a similar technique for tracking inputs and outputs in complex container builds.
https://github.com/ianmiell/shutit/blob/master/shutit_global.py#L1338
This line represents the product of hard-won experience dealing with docker/(p)expect combinations:
"SHUTIT_BACKUP_PS1_%s=$PS1 && PS1='%s' && unset PROMPT_COMMAND"
Backing up the prompt is handy if you want to revert, setting the PS1 with PS1= sets the PS1, and unsetting the PROMPT_COMMAND removes any nasty surprises with the terminal being reset etc.. for the expect.
If the question is about how to ensure it's set when you run the container up (as opposed to building), then you may need to add something to your .bashrc / .profile files depending on how you run up your container. As far as I know there's no way to ensure it with a dockerfile directive and make it persist.
I normally create /home/USER/.bashrc or /root/.bashrc, depending on who the USER of the Dockerfile is. That works well. I've tried
ENV PS1 '# '
but that never worked for me.
Here's a way to set the PS1 when you run the container:
docker run -it \
python:latest \
bash -c "echo \"export PS1='[python:latest] \w$ '\" >> ~/.bashrc && bash"
I made a little wrapper script, to be able to run any image with my custom prompt:
#!/usr/bin/env bash
# ~/bin/docker-run
set -eu
image=$1
docker run -it \
-v $(pwd):/opt/app
-w /opt/app ${image} \
bash -c "echo \"export PS1='[${image}] \w$ '\" >> ~/.bashrc && bash"
In debian 9, for running bash, this worked:
RUN echo 'export PS1="[\$ENV_VAR] \W # "' >> /root/.bashrc
It's generally running as root and I generally know I am in docker, so I wanted to have a prompt that indicated what the container was, so I used an environment variable. And I guess the bash I use loads .bashrc preferentially.
Try setting environment variables using docker options
Example:
docker run \
-ti \
--rm \
--name ansibleserver-debug \
-w /githome/axel-ansible/ \
-v /home/lordjea/githome/:/githome/ \
-e "PS1=DEBUG$(pwd)# " \
lordjea/priv:311 bash
docker --help
Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
Run a command in a new container
Options:
...
-e, --env list Set environment variables
...
You should set that in .profile, not .bashrc.
Just open .profile from your root or home and replace PS1='\u#\h:\w\$ ' with PS1='\e[33;1m\u#\h: \e[31m\W\e[0m\$ ' or whatever you want.
Note that you need to restart your container.
On my MAC I have an alias named lxsh that will start a bash shell using the ubuntu image in my current directory (details). To make the shell's prompt change, I mounted a host file onto /root/.bash_aliases. It's a dirty hack, but it works. The full alias:
alias lxsh='echo "export PS1=\"lxsh[\[$(tput bold)\]\t\[$(tput sgr0)\]\w]\\$\[$(tput sgr0)\] \"" > $TMPDIR/a5ad217e-0f2b-471e-a9f0-a49c4ae73668 && docker run --rm --name lxsh -v $TMPDIR/a5ad217e-0f2b-471e-a9f0-a49c4ae73668:/root/.bash_aliases -v $PWD:$PWD -w $PWD -it ubuntu'
The below solution assumes that you've used Dockerfile USER to set a non-root Linux user for Bash.
What you might have tried without success:
ENV PS1='[docker]$' ## may not work
Using ENV to set PS1 can fail because the value can be overridden by default settings in a preexisting .bashrc when an interactive shell is started. Some Linux distributions are opinionated about PS1 and set it in an initial .bashrc for each user (Ubuntu does this, for example).
The fix is to modify the Dockerfile to set the desired value at the end of the user's .bashrc -- overriding any earlier settings in the script.
FROM ubuntu:20.04
# ...
USER myuser ## the username
RUN echo "PS1='\n[ \u#docker \w ]\n$ '" >>.bashrc

Resources